agentpace 0.9.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,324 @@
1
+ Metadata-Version: 2.5
2
+ Name: agentpace
3
+ Version: 0.9.2
4
+ Summary: Stop estimating agent work in human weeks. agentpace measures how long coding agents actually take: P50/P80/P90 ranges from real Claude Code and Codex runs, the human part stated apart, never derived. Open CC0 dataset, zero-dependency Python CLI, agent skill.
5
+ Project-URL: Homepage, https://mohamedzhioua.github.io/agentpace/
6
+ Project-URL: Repository, https://github.com/mohamedzhioua/agentpace
7
+ Project-URL: Issues, https://github.com/mohamedzhioua/agentpace/issues
8
+ Project-URL: Changelog, https://github.com/mohamedzhioua/agentpace/blob/main/CHANGELOG.md
9
+ Author: Zhioua Mohamed
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: agent-skills,ai-agents,claude-code,codex,coding-agents,dataset,estimation,forecasting
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3 :: Only
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
23
+ Classifier: Topic :: Software Development
24
+ Classifier: Typing :: Typed
25
+ Requires-Python: >=3.10
26
+ Description-Content-Type: text/markdown
27
+
28
+ # agentpace
29
+
30
+ **Stop estimating agent work in human weeks. agentpace measures how long coding agents actually take: a P50/P80/P90 range from real runs, with the human part stated apart, never derived.**
31
+
32
+ ![A speech bubble, dashed and fading, holds a wall calendar shedding blank pages. Beside it a solid stopwatch, its hand a terminal cursor, is measured by two small cursor robots with a tape measure.](https://raw.githubusercontent.com/mohamedzhioua/agentpace/main/docs/assets/hero.webp)
33
+
34
+ [![CI](https://github.com/mohamedzhioua/agentpace/actions/workflows/ci.yml/badge.svg)](https://github.com/mohamedzhioua/agentpace/actions/workflows/ci.yml)
35
+ ![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue)
36
+ [![Code: MIT](https://img.shields.io/badge/code-MIT-blue)](LICENSE)
37
+ [![Data: CC0-1.0](https://img.shields.io/badge/data-CC0--1.0-blue)](data/LICENSE)
38
+
39
+ ## Try it
40
+
41
+ With [uv](https://docs.astral.sh/uv/), this needs no install, no clone and no history of your own:
42
+
43
+ ```bash
44
+ uvx --from git+https://github.com/mohamedzhioua/agentpace agentpace estimate --example
45
+ ```
46
+
47
+ ```text
48
+ <!-- claim:example_output -->
49
+ Plan total on the session clock: P50 2.4 h, P80 5.9 h, P90 9.0 h
50
+ The session clock counts agent runs and the gaps between them, each gap up to the idle cap (900 s by default), so waiting on you between runs sits inside the total up to that cap.
51
+ Human part (review, testing, decisions, waiting between agent turns): not measured. No allowance for it is added to the total above. State it separately; do not derive it from the agent time.
52
+
53
+ task P50 P80 P90 critical cell (n)
54
+ schema 30 min 85 min 2.5 h 100% feature x normal x claude-opus-5-5 (n=205)
55
+ api 30 min 87 min 2.5 h 53% feature x normal x claude-opus-5-5 (n=205)
56
+ ui 30 min 86 min 2.6 h 47% feature x normal x claude-opus-5-5 (n=205)
57
+ docs 72 s 6 min 13 min 18% docs x normal x claude-opus-5-5 (n=0)
58
+ review 3 min 8 min 13 min 82% review x low x claude-opus-5-5 (n=1255)
59
+
60
+ Critical path: schema -> ui -> review (longest in 47% of simulations)
61
+ Effective parallelism at cap 3: 0.90 (from 29 sessions). Throughput set the total in 76% of simulations.
62
+ Method: shrunk. 3383 runs, 47 not completed so excluded. 20000 simulations, seed 20261107.
63
+
64
+ Warnings:
65
+ - cell docs x normal x claude-opus-5-5: n=0, effective n=0.0, below 30. Pooled with all and interval widened.
66
+ <!-- /claim -->
67
+ ```
68
+
69
+ The plan it estimated is [examples/plan.json](examples/plan.json), where each task is one agent run:
70
+
71
+ ```json
72
+ {
73
+ "agent_cap": 3,
74
+ "model": "claude-opus-5-5",
75
+ "tasks": [
76
+ { "id": "schema", "kind": "feature", "risk": "normal" },
77
+ { "id": "api", "kind": "feature", "risk": "normal", "depends_on": ["schema"] },
78
+ { "id": "ui", "kind": "feature", "risk": "normal", "depends_on": ["schema"] },
79
+ { "id": "docs", "kind": "docs", "risk": "normal", "depends_on": ["api"] },
80
+ { "id": "review", "kind": "review", "risk": "low", "depends_on": ["api", "ui"] }
81
+ ]
82
+ }
83
+ ```
84
+
85
+ To estimate your own, write a plan like it and run `agentpace estimate plan.json`, or pass `-` to read it from stdin. In a plan, `depends_on`, `risk` and `model` are optional. Effective parallelism is work divided by elapsed time. It can be below 1, because a session's clock includes the time between runs.
86
+
87
+ Why a range and not one number? Agent run times have a long tail, so any single number misses most of the time. P50 is a coin flip, and P80 is the one to plan on.
88
+
89
+ ### In your agent
90
+
91
+ ```bash
92
+ npx skills add mohamedzhioua/agentpace
93
+ ```
94
+
95
+ Then ask your agent: "How long will the billing feature take?" The skill calls the CLI, so install it first ([Install](#install)). Without it, the skill offers the install command or a portable rule-of-thumb prompt.
96
+
97
+ ## Why agentpace
98
+
99
+ Ask an assistant how long a feature will take and it answers in human-team time, "a few weeks", even when agents will do the work. agentpace answers from measured agent runs instead. Give it a plan of agent tasks and it returns P50/P80/P90 ranges measured from real agent runs and a critical path. It states the human part (review, testing, decisions, waiting) on its own line, and it publishes how often it is wrong. It is a standard-library Python CLI, an agent skill, and an open CC0 dataset.
100
+
101
+ ![How long agent runs took, by task kind](https://raw.githubusercontent.com/mohamedzhioua/agentpace/main/docs/assets/run-ranges.svg)
102
+
103
+ These are <!-- claim:completed -->3,383<!-- /claim --> completed agent runs: Claude Code subagent runs and Codex turns. Half finished within <!-- claim:overall_p50 -->2 min<!-- /claim -->, and one in ten took more than <!-- claim:overall_p90 -->20 min<!-- /claim -->. All of them come from one person so far, so read [Limitations](#limitations) before trusting any of this.
104
+
105
+ ## Does it fit your setup?
106
+
107
+ | You want to | Works with today |
108
+ |---|---|
109
+ | Estimate a plan | Anywhere. The seed data ships inside the package, so no history of your own is needed |
110
+ | Log your own runs | Claude Code, subagent runs only: work Claude Code hands to a subagent, not the main conversation. Your rows pool with the seed, and `--data ~/.agentpace/runs.jsonl` uses only yours |
111
+ | Log your own Codex runs | Codex, one agent turn per run: `agentpace ingest --source codex` reads `~/.codex/sessions`. The published rows include Codex turns, and the backtest scores Codex on its own |
112
+ | Log your own Gemini CLI runs | Experimental: `agentpace ingest --source gemini-cli` reads `~/.gemini/tmp`, one agent turn per run. The adapter is built from the Gemini CLI source, not yet verified on real sessions, and no published rows come from it (`validate` rejects them until the adapter is verified; [how to verify it](docs/verify-adapter.md)). Report problems in an [issue](https://github.com/mohamedzhioua/agentpace/issues) |
113
+ | Log your own OpenCode runs | Experimental: `agentpace ingest --source opencode` reads `~/.local/share/opencode/opencode.db`. The adapter is built from the OpenCode source, not yet verified on real sessions, and no published rows come from it (`validate` rejects them until the adapter is verified; [how to verify it](docs/verify-adapter.md)). Report problems in an [issue](https://github.com/mohamedzhioua/agentpace/issues) |
114
+ | Log your own Cline runs | Experimental: `agentpace ingest --source cline` reads Cline's task folders in VS Code's global storage, one agent turn per run. The adapter is built from the Cline source, not yet verified on real sessions, and no published rows come from it (`validate` rejects them until the adapter is verified; [how to verify it](docs/verify-adapter.md)). Report problems in an [issue](https://github.com/mohamedzhioua/agentpace/issues) |
115
+ | Another harness | Not yet. The adapter interface takes one module per harness |
116
+
117
+ ## Install
118
+
119
+ ```bash
120
+ uv tool install git+https://github.com/mohamedzhioua/agentpace
121
+ ```
122
+
123
+ `pipx install git+https://github.com/mohamedzhioua/agentpace` works too. It needs Python 3.10 or later and has no dependencies. agentpace is not on PyPI yet, which is why both commands install from git. After installing, drop the `uvx --from ...` prefix from the command above.
124
+
125
+ Then add the agent skills:
126
+
127
+ ```bash
128
+ npx skills add mohamedzhioua/agentpace
129
+ ```
130
+
131
+ Without Node, copy the four folders under [skills/](skills/) into your agent's skills folder, for example `~/.claude/skills/` for Claude Code. No skill-capable agent? Paste [the portable prompt](skills/agentpace/assets/portable-prompt.md) into any assistant.
132
+
133
+ ## Skills
134
+
135
+ | Skill | Say this | You get |
136
+ |---|---|---|
137
+ | [`agentpace`](skills/agentpace/SKILL.md) | "How long will the billing feature take?", or "my manager says this is a 3-month project" | The work split into agent tasks, a measured P50/P80/P90 range with its critical path, the human part on its own line, and any quoted timeline shown beside it as unverified |
138
+ | [`/pace-estimate`](skills/pace-estimate/SKILL.md) | `/pace-estimate plan.json`, or a task list | The same estimate for a plan you hand it |
139
+ | [`/pace-log`](skills/pace-log/SKILL.md) | `/pace-log`, "log my agent runs", "that run was a bug fix" | Your runs ingested into `~/.agentpace`, labels corrected, and the opt-in hook that logs each run as it finishes |
140
+ | [`/pace-share`](skills/pace-share/SKILL.md) | `/pace-share`, only when you ask | The exact rows you could contribute, previewed first. It writes a file only after you say yes, and sends nothing |
141
+
142
+ `agentpace` triggers by itself on questions about how long software work will take. The three `/pace-*` skills run when you call them. The [portable prompt](skills/agentpace/assets/portable-prompt.md) gives a rule-of-thumb version of the same answer in assistants without skills.
143
+
144
+ ### Re-answer a quoted timeline
145
+
146
+ Suppose someone has called a customer-import feature "a 3-month project". The skill splits it into agent tasks, as in [examples/quote-plan.json](examples/quote-plan.json), and passes the quote on exactly as it was given:
147
+
148
+ ```bash
149
+ agentpace estimate examples/quote-plan.json --quoted "3 months"
150
+ ```
151
+
152
+ ```text
153
+ <!-- claim:quote_example_output -->
154
+ Plan total on the session clock: P50 4.3 h, P80 10.3 h, P90 15.7 h
155
+ Quoted: "3 months" (calendar time, as quoted; unverified, not converted)
156
+ The session clock counts agent runs and the gaps between them, each gap up to the idle cap (900 s by default), so waiting on you between runs sits inside the total up to that cap.
157
+ Human part (review, testing, decisions, waiting between agent turns): not measured. No allowance for it is added to the total above. State it separately; do not derive it from the agent time.
158
+
159
+ task P50 P80 P90 critical cell (n)
160
+ schema 30 min 85 min 2.5 h 100% feature x normal x claude-opus-5-5 (n=205)
161
+ importer 30 min 86 min 2.6 h 40% feature x normal x claude-opus-5-5 (n=205)
162
+ api 30 min 87 min 2.5 h 60% feature x normal x claude-opus-5-5 (n=205)
163
+ settings-ui 31 min 86 min 2.5 h 32% feature x normal x claude-opus-5-5 (n=205)
164
+ tests 38 min 2.1 h 3.8 h 68% tests x normal x claude-opus-5-5 (n=2)
165
+ review 3 min 8 min 13 min 100% review x low x claude-opus-5-5 (n=1255)
166
+
167
+ Critical path: schema -> importer -> tests -> review (longest in 40% of simulations)
168
+ Effective parallelism at cap 3: 0.90 (from 29 sessions). Throughput set the total in 78% of simulations.
169
+ Method: shrunk. 3383 runs, 47 not completed so excluded. 20000 simulations, seed 20261107.
170
+
171
+ Warnings:
172
+ - cell tests x normal x claude-opus-5-5: n=2, effective n=2.0, below 30. Pooled with all and interval widened.
173
+ <!-- /claim -->
174
+ ```
175
+
176
+ The quote is calendar time, as quoted, and nothing has checked it. The range is built from measured agent time on the session clock, which counts the gaps between runs up to the idle cap. The human part is stated apart, on its own line, and no allowance for it is added to either. The quote is shown beside the range, never converted into agent time or set against it.
177
+
178
+ ## Commands
179
+
180
+ | Use | What it does |
181
+ |---|---|
182
+ | `agentpace estimate <plan>` | P50, P80 and P90 for a plan, and the human part on its own line |
183
+ | `agentpace estimate <plan> --data ~/.agentpace/runs.jsonl` | The same, from your own ingested runs only |
184
+ | `agentpace estimate <plan> --record --quoted "3 weeks"` | Keep the forecast on your machine to score later, with any timeline someone already quoted |
185
+ | `agentpace ingest [path]` | Read local agent history into rows |
186
+ | `agentpace runs` | List recent runs and their references |
187
+ | `agentpace label <ref>` | Correct the kind or risk of a run |
188
+ | `agentpace share` | Preview exact rows, or write a file to contribute |
189
+ | `agentpace score [id]` | Score a recorded forecast against a session that started after it, or see how your forecasts held up |
190
+ | `agentpace turns` | Measure how long you wait between agent turns, from your own main sessions. Kept local, never shared |
191
+
192
+ | Maintain | What it does |
193
+ |---|---|
194
+ | `agentpace backtest` | Regenerate the published evaluation |
195
+ | `agentpace validate` | Check data files: the bundled seed by default; contributors pass `data/runs` |
196
+ | `agentpace site` | Refresh the data inside the static page |
197
+ | `agentpace claims` | Check every number in this README against the data |
198
+
199
+ `agentpace ingest` reads Claude Code subagent transcripts from `~/.claude/projects` and keeps rows in `~/.agentpace`, on your machine. A second run reads only what changed. To log every run as it finishes, add the opt-in hook that [`/pace-log`](skills/pace-log/SKILL.md) shows.
200
+
201
+ There is also a [leaderboard](https://mohamedzhioua.github.io/agentpace/) of median, P75 and P90 by model, kind and risk.
202
+
203
+ ## Backtest: how often it is wrong
204
+
205
+ **Bottom line.** On <!-- claim:plan_sessions -->56<!-- /claim --> held-out sessions, the whole-session P80 covered <!-- claim:plan_p80 -->80% (CI 70% to 91%)<!-- /claim --> and the P90 covered <!-- claim:plan_p90 -->91% (CI 84% to 98%)<!-- /claim -->. For a single task, the P80 covered <!-- claim:task_p80 -->77.7% (CI 71.4% to 83.8%)<!-- /claim -->, but the median miss of its P50 is <!-- claim:task_mdape -->78%<!-- /claim -->, so plan on the range, never the middle. Calibration drifts from week to week: per-session P80 coverage ran from <!-- claim:weekly_p80 -->66% to 86%<!-- /claim -->.
206
+
207
+ Every number here comes from the published rows. `agentpace backtest` regenerates them, and CI fails if they drift. The headline scores Claude Code sessions, the population the method was chosen on. Codex is [scored on its own](docs/backtest.md#by-harness). The [full report](docs/backtest.md) has every split, every baseline and every loss.
208
+
209
+ Forecasts use only what is known before a run: model, kind and risk. Whole sessions are held out, so no run can leak into its own forecast. These headline numbers come from the same time folds that chose the method, so treat them as slightly optimistic. Weeks after <!-- claim:selection_last_week -->2026-W45<!-- /claim --> form a locked holdout that never takes part in selection. Its status: <!-- claim:locked_status -->not enough data (no weeks after 2026-W45 yet)<!-- /claim -->. Every interval below is a 95% bootstrap interval that resamples whole sessions.
210
+
211
+ <details>
212
+ <summary>Every number, with intervals and baselines</summary>
213
+
214
+ **Whole sessions.** Each of <!-- claim:plan_sessions -->56<!-- /claim --> later sessions with at least 5 completed runs was predicted from earlier weeks only. This is the only direct test of plan totals.
215
+
216
+ | Forecast | Target | Got |
217
+ |---|---:|---:|
218
+ | Session finished within P50 | 50% | <!-- claim:plan_p50 -->59% (CI 45% to 71%)<!-- /claim --> |
219
+ | Session finished within P80 | 80% | <!-- claim:plan_p80 -->80% (CI 70% to 91%)<!-- /claim --> |
220
+ | Session finished within P90 | 90% | <!-- claim:plan_p90 -->91% (CI 84% to 98%)<!-- /claim --> |
221
+
222
+ P80 and P90 coverage land near target, but with this few sessions the intervals are wide, and so are the ranges: P90 is typically <!-- claim:plan_width -->2.7x<!-- /claim --> P50, and the median error of the P50 is <!-- claim:plan_mdape -->67%<!-- /claim -->. The test also uses information a real forecast would not have, namely the session's actual task list and peak concurrency, and real dependencies are not recorded. So it tests the throughput model, not dependency planning. Pinball loss on whole sessions is <!-- claim:plan_pinball -->19720 (CI 13260 to 28000)<!-- /claim --> seconds, against <!-- claim:naive_plan_pinball -->37990<!-- /claim --> for a sum of medians.
223
+
224
+ **Single tasks.** On the time split, with each session counting equally:
225
+
226
+ | Method | P80 coverage (target 80%) | Pinball loss (lower is better) | Its pinball minus agentpace's |
227
+ |---|---:|---:|---:|
228
+ | agentpace (`<!-- claim:winner -->shrunk<!-- /claim -->`) | <!-- claim:task_p80 -->77.7% (CI 71.4% to 83.8%)<!-- /claim --> | <!-- claim:task_pinball -->1047 (CI 831 to 1316)<!-- /claim --> | n/a |
229
+ | Fixed 3 minutes per round | n/a | <!-- claim:rounds_pinball -->1308<!-- /claim --> | <!-- claim:rounds_pinball_gap -->+75 to +467<!-- /claim --> |
230
+ | Global median | n/a | <!-- claim:median_pinball -->1719<!-- /claim --> | <!-- claim:median_pinball_gap -->+373 to +991<!-- /claim --> |
231
+ | Naive human-time guess | n/a | <!-- claim:human_pinball -->7569<!-- /claim --> | <!-- claim:human_pinball_gap -->+5725 to +7439<!-- /claim --> |
232
+
233
+ The human-time guess is a hand-written table, an assumption rather than a measurement. A difference interval wholly above zero means that baseline is worse at the 95% level.
234
+
235
+ **Calibration is not stable from week to week.** That P80 coverage pools <!-- claim:weeks_tested -->4<!-- /claim --> test weeks, and the pooled figure hides misses in both directions. Week by week it ran from <!-- claim:weekly_p80 -->66% to 86%<!-- /claim --> with each session counting equally, and from <!-- claim:weekly_p80_row -->60% to 94%<!-- /claim --> with each run counting equally. In the latest week, <!-- claim:latest_week -->2026-W45<!-- /claim -->, it was <!-- claim:latest_week_p80 -->66%<!-- /claim --> per session and <!-- claim:latest_week_p80_row -->60%<!-- /claim --> per run, from only <!-- claim:latest_week_sessions -->8<!-- /claim --> sessions. Read the pooled P80 as an average over weeks, not a promise for any one week. The [week-by-week table](docs/backtest.md#time-split-week-by-week) has every fold.
236
+
237
+ ![P80 coverage by method](https://raw.githubusercontent.com/mohamedzhioua/agentpace/main/docs/assets/backtest-coverage.svg)
238
+
239
+ </details>
240
+
241
+ **Where it falls short.**
242
+
243
+ - The median error on a single task is <!-- claim:task_mdape -->78%<!-- /claim -->. Use the range, not the middle.
244
+ - Pooled, P80 coverage is <!-- claim:task_p80_row -->88.8%<!-- /claim --> when each run counts equally rather than each session, so the ranges are too wide for the small, fast runs that dominate the row count.
245
+ - A global median beats agentpace on MAPE (<!-- claim:median_mape -->234%<!-- /claim --> against <!-- claim:task_mape -->494%<!-- /claim -->), and a sum of medians beats it on plan MAPE (<!-- claim:naive_plan_mape -->85%<!-- /claim --> against <!-- claim:plan_mape -->249%<!-- /claim -->), though that sum covers only <!-- claim:naive_plan_p80 -->5%<!-- /claim --> of sessions at P80. MAPE punishes the long tail of over-forecasts that honest ranges need.
246
+ - The report lists <!-- claim:loss_count -->20<!-- /claim --> places where a baseline won. That list is generated, so it cannot be edited out.
247
+ - On the project split, which runs over both harnesses and where the largest project, a <!-- claim:project_top_harness -->codex<!-- /claim --> one, holds <!-- claim:project_top_sessions -->137 of 212<!-- /claim --> held-out sessions, P80 coverage is <!-- claim:project_p80 -->88.9%<!-- /claim -->. The contributor split <!-- claim:contributor_split -->could not run (1 contributor)<!-- /claim -->.
248
+ - The session-weighted design this project started with did not beat the simpler unweighted one, so the simpler one shipped. The selection rule was fixed before the first result. Scoring it on Claude Code sessions only was decided after a run with Codex rows pooled in had been seen, and that [pooled result](docs/backtest.md#pooled-for-the-record) is printed in the report.
249
+
250
+ ## Privacy
251
+
252
+ agentpace never stores prompts, code or commit messages, and the rows you publish hold no content, file paths or repo names. Paths live in one local place, the ingest cache in `~/.agentpace/`, which is never shared. It holds two kinds: the path of each transcript, so the next ingest re-reads only what changed, and the project folder (for Codex, the working folder), which reaches a row only as a keyed hash.
253
+
254
+ - **What gets read.** From each transcript: timestamps, model ids, token counts, tool names, error flags and two metadata keys, plus the project folder as a hash input. JSON is decoded one line at a time, so other text passes through memory, but only those values are copied out. A test plants marker strings in every sensitive field and proves none reach any output.
255
+ - **What a row holds.** Only the fields in [schema/run.schema.json](schema/run.schema.json). Every string is an enum or a strict pattern, so free text has nowhere to land.
256
+ - **Who you are.** Keyed hashes under a random secret that never leaves your machine. No email, handle or hostname goes in, so nobody can reverse them by guessing names.
257
+ - **Nothing is sent.** There is no network code in this package at all, and a test fails if any is added. Contributing is a git push you run yourself. The site loads nothing from anywhere else.
258
+
259
+ Rows are not anonymous in every sense. They link to each other, they show roughly when you worked, and a pull request ties them to your GitHub account. `agentpace share` says so before it writes anything.
260
+
261
+ ## Contribute your runs
262
+
263
+ Sharing is opt-in, and your rows join a public-domain dataset.
264
+
265
+ ```bash
266
+ git clone https://github.com/<your-fork>/agentpace && cd agentpace
267
+ uv tool install . # or pipx install .
268
+ agentpace ingest
269
+ agentpace share --dry-run # prints the exact rows and writes nothing
270
+ agentpace share --write # adds or extends one file under data/runs, and still sends nothing
271
+ agentpace validate data/runs # the same checks CI runs
272
+ ```
273
+
274
+ Then open a pull request with that one file. A data pull request dedicates your rows to the public domain under CC0-1.0. See [CONTRIBUTING.md](CONTRIBUTING.md).
275
+
276
+ The most useful thing you can do is contribute: the contributor split cannot run until a second person does.
277
+
278
+ ## How it compares
279
+
280
+ Audited at the commits listed in [docs/DESIGN.md](docs/DESIGN.md).
281
+
282
+ | | agentpace | [agent-estimate](https://github.com/kiloloop/agent-estimate) | [claude-eta](https://github.com/MMMProd-Org/claude-eta) | [agent-estimation](https://github.com/ZhangHanDong/agent-estimation) | [web-dev-estimation](https://github.com/ecappa/web-dev-estimation) | [mythical-agent-month](https://github.com/MedAdemBHA/mythical-agent-month) |
283
+ |---|---|---|---|---|---|---|
284
+ | **Base** | Observed run durations | PERT tiers in minutes | Per-turn seconds | Tool-call rounds | Human time with multipliers | Size tables with PERT |
285
+ | **Numbers come from** | Published rows | Hand-set, with a small private sample | Your own hook data | Hand-set | Hand-set | One 398-run build, unpublished |
286
+ | **Output** | P50, P80, P90 | O/M/P and sigma | P50, P80 | Low to high | Mandatory range | Likely, range, plan |
287
+ | **Runs in repo** | Yes | No | No | No | No | No, a shape file only |
288
+ | **Multi-agent** | Graph simulation, learned throughput | Graph, wave planning | No | Waves | No | Critical path, default 1.8 |
289
+ | **Published check** | Time and project holdouts, regenerated by CI | Coverage audit, needs OACP files | Walk-forward: n=285, P80 76.8%, MdAPE 79% | None | Prompt evals | One holdout: -24% and -37% |
290
+ | **Runtime deps** | None | typer, pydantic, networkx, others | None | None | None | None |
291
+
292
+ Each of these does something better than agentpace:
293
+
294
+ - **agent-estimate** binds forecasts to receipts, so one issued after work started cannot score. It also forecasts token cost, and ships as a pip package and a GitHub Action.
295
+ - **claude-eta** gives live per-turn ETAs inside a session, evaluates itself walk-forward on your own history, and has consent-gated community sharing and a repair-loop detector.
296
+ - **agent-estimation** is the simplest and most teachable model here, and it needs no data at all.
297
+ - **web-dev-estimation** has the best skill structure, with batch and re-estimate modes that work from documents before any history exists.
298
+ - **mythical-agent-month** separates machine, human and waiting time, tracks usage budgets, and openly publishes its own held-out miss.
299
+
300
+ ## Limitations
301
+
302
+ - **One person's workflow.** Every run comes from <!-- claim:contributors -->1<!-- /claim --> contributor, across <!-- claim:projects -->21<!-- /claim --> projects and <!-- claim:sessions -->293<!-- /claim --> sessions, from <!-- claim:first_week -->2026-W40<!-- /claim --> to <!-- claim:last_week -->2026-W45<!-- /claim -->. One project holds <!-- claim:top_project -->67%<!-- /claim --> of runs, and three sessions hold <!-- claim:top_sessions -->45%<!-- /claim -->. It includes heavy automated fan-out, so it may not resemble your setup.
303
+ - **Not a model speed ranking.** People send harder work to stronger models, so a slower row may just mean harder tasks.
304
+ - **`feature` means any implementation work.** Without reading prompts, metadata cannot separate features, bug fixes and refactors. Those kinds stay thin until people label runs.
305
+ - **Retries are not separated.** A run's duration includes any test-fix loop inside it. `retries` counts errored tool results, a proxy, because a real retry cannot be seen without reading content, and no field that describes what happened in a run (`retries`, `tool_calls`, `tokens`, `outcome`) ever predicts a duration. Codex upkeep sessions (`compact`) are skipped; nothing else is split out.
306
+ - **Pooled by kind, risk and model only.** A cell with fewer than 30 runs leans on broader cells, with a warning. Repository size is not recorded, and `size` is an edit count measured after the run, so neither can segment the published runs. Long integration work has no cell of its own.
307
+ - **Two harnesses, still one person.** The published rows hold Claude Code subagent runs and, since 0.6.0, Codex turns, all from the same contributor. Codex is scored on its own, never in the headline. Each Codex exec session is a single turn, so the session effect and the parallelism factor learn nothing from Codex, and a Codex plan borrows Claude Code's session structure. Gemini CLI, OpenCode and Cline have experimental adapters: built from each tool's source, not yet verified on real sessions, with no published rows (`validate` rejects them until each adapter is verified; [how to verify one](docs/verify-adapter.md)), and problems go in an [issue](https://github.com/mohamedzhioua/agentpace/issues). Other harnesses have no adapter.
308
+ - **No human allowance, and short waits sit inside the clock.** The plan total is a forecast on the session clock, which counts agent runs and the gaps between them, each gap up to the idle cap (900 s in the published rows). So a wait on you shorter than that sits inside the total, a longer one is clipped at the cap, and no allowance for review, testing or decisions is added. Every estimate says so on its own lines and never derives the human part from agent time. `agentpace turns` measures your own wait per human turn from your main-session timestamps and keeps it on your machine. That is elapsed time, not effort, shown beside the range and never added to it.
309
+ - **Failed runs are under-counted.** Only runs with a clear completion signal train the estimator, so P90 may run low.
310
+ - **Size is not used by default.** Stored size is measured after a run, so it would leak the answer into the forecast.
311
+ - **The transcript format is undocumented.** It may change, and Claude Code removes old transcripts, so run `agentpace ingest` regularly.
312
+ - **Dependencies are untested.** The whole-session test cannot see real dependencies.
313
+
314
+ ## Development
315
+
316
+ ```bash
317
+ PYTHONPATH=src python -m unittest discover -s tests -t .
318
+ ```
319
+
320
+ The tests need nothing installed. All the math is in [src/agentpace/estimate.py](src/agentpace/estimate.py). The reasoning behind the design is in [docs/DESIGN.md](docs/DESIGN.md).
321
+
322
+ ## License
323
+
324
+ Code: [MIT](LICENSE). Data: [CC0-1.0](data/LICENSE).
@@ -0,0 +1,39 @@
1
+ agentpace/__init__.py,sha256=HG6NrvMLeTgjuJwRzRs-bp7a6LIst5sROh6TwPK--F8,97
2
+ agentpace/__main__.py,sha256=587d2znmwZyRDb22md59qdOTYOJBWZphFmXbf5IoBWw,128
3
+ agentpace/backtest.py,sha256=yrwn3qG5TPME5V3aQ1PaAmKBKnQh4wlUq1jcPhehxBo,33104
4
+ agentpace/cache.py,sha256=xYUihEcX59hdtcofOEmYDuo_t_Pcl8XtvZtt35RveiU,4938
5
+ agentpace/charts.py,sha256=rRwy7FJcjAnt1So5eN2qCX3saFoI01NKxgnfNevo-jk,6905
6
+ agentpace/claims.py,sha256=uBKUarsvKVBkueK1SF_c3NctOz5lERxPapmIdrhHHNk,7350
7
+ agentpace/classify.py,sha256=ATEiyTBajCfQSKCwrhfVNMyLTqPtLWpxIuHzjIfGOo8,1719
8
+ agentpace/cli.py,sha256=x5oGevxGSnkSZ7ok14bt6uXa5Fm60aFgEjTZ8u_ftJ8,30650
9
+ agentpace/estimate.py,sha256=VlHrYlWqYjTzyvRfDfcR-bjKv-MPLvichuuZ-CbjppI,26060
10
+ agentpace/forecasts.py,sha256=AM_E1rcd7pula3Qv20ueeeeZu3SngBB8Jfnr8dGctcY,9702
11
+ agentpace/ingest.py,sha256=vYoRYNLcZMIge18mC3lj_ykT0FCa7LYCW7tcJiWQJHY,13000
12
+ agentpace/paths.py,sha256=lgz_XBPXoWkEnif7HCEXHKEO4tVF7ClVe-AAzGRZE4o,1795
13
+ agentpace/pseudonym.py,sha256=-a5ffU5VZqjX6BS7DhjHK15RbYt8wHOoUaKFrc-o39s,1632
14
+ agentpace/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
+ agentpace/render.py,sha256=Si0OvncR4FWaVu8xqPkl-vLzlR6L4bgz3T3W8n2jnNE,6683
16
+ agentpace/report.py,sha256=hPF6x3gwJy2oHXsT2RAYR_7p8GuV5sUqUogcDncN1Pw,21342
17
+ agentpace/schema.py,sha256=2w_q0WP4cwihnUoMoQUHfu4QyGguNqGbFEgwiuxfTmE,4620
18
+ agentpace/share.py,sha256=PHNschKEgaTkaIpM9ArpQkIpnlwfvWt0Ly_PUj7rwks,5132
19
+ agentpace/site.py,sha256=bMfrbVLAIZKYoNL9Ydre7VH8cBwgwF7FHmhLH14eFU8,5299
20
+ agentpace/turns.py,sha256=O-TpTw0B8j8Tfd8Fs2n756mnf8QDRobSTKEBeiaYiZA,9564
21
+ agentpace/validate.py,sha256=jh4DzKO0sAKkeVGJs-Tq7SHAl05PSthJPOzje6mSq-g,4425
22
+ agentpace/adapters/__init__.py,sha256=_TS5Mq-qbZYvw8X3ucZLQSrv_09OZX-qEJU9gs13bIE,1146
23
+ agentpace/adapters/base.py,sha256=VWXJuPCY_GYxuQPLHua-OLVE5eZOVA7Oje9W6krTq30,2506
24
+ agentpace/adapters/claude_code.py,sha256=mM71KOzgwISZWyDJL51foPw6nyECo50ppOYmhDhDIxo,9907
25
+ agentpace/adapters/cline.py,sha256=WfHIASq2kx3kQAiAFcIJt26kqEdjpGEWNkt8d6kCD8c,17893
26
+ agentpace/adapters/codex.py,sha256=yxdgPHe8sW60nyGDQNWEFhlDwoOFOu6c2XNbj0ZGR78,11979
27
+ agentpace/adapters/gemini_cli.py,sha256=ssNtui8E8MQ1foBlF2SGIGwbC-qh27aDge9sm5id4ig,14603
28
+ agentpace/adapters/opencode.py,sha256=oH8Kn2AdrKFgWbbZ04HTEXyOr7o0Wt8Y1SCZYRlyyac,16592
29
+ agentpace/_bundled/DATA-LICENSE,sha256=ogEPNDSH0_dhiv_lT3ifVIdgIzHAqNA_SemnxUfPBJk,7048
30
+ agentpace/_bundled/example-plan.json,sha256=9aHy05TFxz_EE23YWf58JflCrDzV42fr74cf58U2Rds,461
31
+ agentpace/_bundled/run.schema.json,sha256=un_UQKzOudFBdCskJJfISkaiYo07pZqo-41Ure4ymZc,3071
32
+ agentpace/_bundled/runs/4546788e7930eccd-2026-W40-2026-W45.jsonl,sha256=Nl_NVYFRsVzdYlRXH26MgkxUI4pOojw1pGXeHB6ZrLQ,1024337
33
+ agentpace/_bundled/runs/4546788e7930eccd-2026-W44-2026-W45.jsonl,sha256=_pYAmq_qzbYswSG3cL7s0PQfxUxOZ6nM12F45mlRvEE,67613
34
+ agentpace/_bundled/turn.schema.json,sha256=QEx-34mWd0Ht-VznzL0YLzg6CfYrp6WptzIG_-PMvcY,1282
35
+ agentpace-0.9.2.dist-info/METADATA,sha256=JSBAGsdv-OrOQ_dgMFOv1lHsCn5Lwdjgo84aDGPneZs,28872
36
+ agentpace-0.9.2.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
37
+ agentpace-0.9.2.dist-info/entry_points.txt,sha256=DwGYpqwKX5sarV_u8GTcrCEOUh5TFB9VUguY-P_zvgI,49
38
+ agentpace-0.9.2.dist-info/licenses/LICENSE,sha256=joL0MYSh7wiFJFVAKh2C-me1g8mZaPRmEWPlJbrVpwk,1071
39
+ agentpace-0.9.2.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.33.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ agentpace = agentpace.cli:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Zhioua Mohamed
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.