agentprof 0.1.0__tar.gz

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.
Files changed (54) hide show
  1. agentprof-0.1.0/LICENSE +21 -0
  2. agentprof-0.1.0/PKG-INFO +177 -0
  3. agentprof-0.1.0/README.md +152 -0
  4. agentprof-0.1.0/pyproject.toml +95 -0
  5. agentprof-0.1.0/pyproject.toml.orig +67 -0
  6. agentprof-0.1.0/src/agentprof/__init__.py +7 -0
  7. agentprof-0.1.0/src/agentprof/adapters/__init__.py +15 -0
  8. agentprof-0.1.0/src/agentprof/adapters/base.py +79 -0
  9. agentprof-0.1.0/src/agentprof/adapters/claude_code/__init__.py +3 -0
  10. agentprof-0.1.0/src/agentprof/adapters/claude_code/adapter.py +133 -0
  11. agentprof-0.1.0/src/agentprof/adapters/claude_code/discovery.py +79 -0
  12. agentprof-0.1.0/src/agentprof/adapters/claude_code/prompts.py +44 -0
  13. agentprof-0.1.0/src/agentprof/adapters/claude_code/tools.py +102 -0
  14. agentprof-0.1.0/src/agentprof/adapters/claude_code/transcript.py +264 -0
  15. agentprof-0.1.0/src/agentprof/adapters/claude_code/tree.py +492 -0
  16. agentprof-0.1.0/src/agentprof/adapters/codex/__init__.py +3 -0
  17. agentprof-0.1.0/src/agentprof/adapters/codex/adapter.py +164 -0
  18. agentprof-0.1.0/src/agentprof/adapters/codex/discovery.py +117 -0
  19. agentprof-0.1.0/src/agentprof/adapters/codex/prompts.py +16 -0
  20. agentprof-0.1.0/src/agentprof/adapters/codex/rollout.py +328 -0
  21. agentprof-0.1.0/src/agentprof/adapters/codex/tools.py +97 -0
  22. agentprof-0.1.0/src/agentprof/adapters/codex/tree.py +311 -0
  23. agentprof-0.1.0/src/agentprof/adapters/copilot_vscode/__init__.py +3 -0
  24. agentprof-0.1.0/src/agentprof/adapters/copilot_vscode/adapter.py +166 -0
  25. agentprof-0.1.0/src/agentprof/adapters/copilot_vscode/debuglog.py +136 -0
  26. agentprof-0.1.0/src/agentprof/adapters/copilot_vscode/discovery.py +153 -0
  27. agentprof-0.1.0/src/agentprof/adapters/copilot_vscode/session.py +281 -0
  28. agentprof-0.1.0/src/agentprof/adapters/copilot_vscode/tools.py +127 -0
  29. agentprof-0.1.0/src/agentprof/adapters/copilot_vscode/transcript.py +176 -0
  30. agentprof-0.1.0/src/agentprof/adapters/copilot_vscode/tree.py +325 -0
  31. agentprof-0.1.0/src/agentprof/adapters/execution.py +64 -0
  32. agentprof-0.1.0/src/agentprof/adapters/timestamps.py +13 -0
  33. agentprof-0.1.0/src/agentprof/adapters/turns.py +24 -0
  34. agentprof-0.1.0/src/agentprof/analysis/__init__.py +3 -0
  35. agentprof-0.1.0/src/agentprof/analysis/agent_summary.py +161 -0
  36. agentprof-0.1.0/src/agentprof/analysis/call_context.py +101 -0
  37. agentprof-0.1.0/src/agentprof/analysis/evidence_findings.py +151 -0
  38. agentprof-0.1.0/src/agentprof/analysis/execution.py +39 -0
  39. agentprof-0.1.0/src/agentprof/analysis/heuristics.py +306 -0
  40. agentprof-0.1.0/src/agentprof/analysis/pipeline.py +31 -0
  41. agentprof-0.1.0/src/agentprof/analysis/rollup.py +196 -0
  42. agentprof-0.1.0/src/agentprof/cli.py +141 -0
  43. agentprof-0.1.0/src/agentprof/model.py +341 -0
  44. agentprof-0.1.0/src/agentprof/pricing.json +23 -0
  45. agentprof-0.1.0/src/agentprof/pricing.py +120 -0
  46. agentprof-0.1.0/src/agentprof/registry.py +304 -0
  47. agentprof-0.1.0/src/agentprof/server/__init__.py +3 -0
  48. agentprof-0.1.0/src/agentprof/server/app.py +399 -0
  49. agentprof-0.1.0/src/agentprof/server/openapi.py +31 -0
  50. agentprof-0.1.0/src/agentprof/server/pricing_schema.py +40 -0
  51. agentprof-0.1.0/src/agentprof/server/schemas.py +579 -0
  52. agentprof-0.1.0/src/agentprof/server/static/assets/index-C4HEqUVf.css +1 -0
  53. agentprof-0.1.0/src/agentprof/server/static/assets/index-ZsPn1H3d.js +58 -0
  54. agentprof-0.1.0/src/agentprof/server/static/index.html +14 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 epicodic
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.
@@ -0,0 +1,177 @@
1
+ Metadata-Version: 2.4
2
+ Name: agentprof
3
+ Version: 0.1.0
4
+ Summary: Analyse AI coding agent sessions: call trees, timings, tokens, cost and waste.
5
+ Keywords: ai,agents,copilot,claude-code,llm,tokens,cost,observability
6
+ Author: epicodic
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Environment :: Web Environment
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Classifier: Topic :: Software Development :: Quality Assurance
18
+ Requires-Dist: fastapi>=0.120
19
+ Requires-Dist: uvicorn>=0.38
20
+ Requires-Python: >=3.12
21
+ Project-URL: Homepage, https://github.com/epicodic/agentprof
22
+ Project-URL: Repository, https://github.com/epicodic/agentprof
23
+ Project-URL: Issues, https://github.com/epicodic/agentprof/issues
24
+ Description-Content-Type: text/markdown
25
+
26
+ # agentprof
27
+
28
+ [![PyPI](https://img.shields.io/pypi/v/agentprof?cacheSeconds=3600)](https://pypi.org/project/agentprof/)
29
+ [![Python versions](https://img.shields.io/pypi/pyversions/agentprof?cacheSeconds=3600)](https://pypi.org/project/agentprof/)
30
+ [![CI](https://github.com/epicodic/agentprof/actions/workflows/ci.yml/badge.svg)](https://github.com/epicodic/agentprof/actions/workflows/ci.yml)
31
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](https://github.com/epicodic/agentprof/blob/main/LICENSE)
32
+
33
+ **A profiler for AI coding agents: see where your agents spend time, tokens and money.**
34
+
35
+ agentprof reads the session logs that Claude Code, OpenAI Codex CLI and VS Code Copilot Chat already write on your machine.
36
+ It shows each session as a call tree of turns, subagents and tool calls, with an inline timeline, token counts, context growth, costs and hints about likely waste.
37
+ Everything runs locally, so your sessions never leave your machine.
38
+
39
+ ![A Claude Code session as a call tree with timeline, cost, tokens and context per row](https://media.githubusercontent.com/media/epicodic/agentprof/main/docs/images/session-tree.png)
40
+
41
+ ## Features
42
+
43
+ - **Call tree with timeline**: every prompt, subagent and tool call becomes a row with its duration, cost, tokens and peak context, next to a timeline bar for when it ran.
44
+ Nested subagents get their own colour-coded agent numbers, so you can follow a delegation chain at a glance.
45
+ - **Cost and token accounting**: costs and tokens are given both per node and rolled up per subtree, with input, output, cache read and cache write tokens counted separately.
46
+ Estimated values are marked `≈`, and values the logs do not contain are shown as `–` instead of being guessed.
47
+ - **Context tracking**: see how the context window grows call by call, where it peaks and where it was compacted.
48
+ - **Agent summary**: one row per agent with its model, cache TTL, resumes, duration, own cost, share of the session cost and token breakdown.
49
+ - **Node details**: open any turn or agent to see its timeline, cost per LLM call, context chart, subagents and a searchable list of LLM and tool calls, down to the raw prompt, result and tool arguments.
50
+ - **Waste findings**: hints, not verdicts, about where time and money may have gone (see [Findings](#findings)).
51
+ - **Live updates**: the session list fills in within seconds, and open sessions update while an agent is still working.
52
+ - **JSON API for AI agents**: everything in the UI is also available as compact JSON, so an AI agent can analyse sessions itself, including how the agents and subagents in them worked together.
53
+
54
+ ![Node details with timeline, cost per LLM call, context growth, subagents and LLM calls](https://media.githubusercontent.com/media/epicodic/agentprof/main/docs/images/node-details.png)
55
+
56
+ ## Installation
57
+
58
+ agentprof is a command-line tool that starts a local web app.
59
+ Install it in its own isolated environment with [uv](https://docs.astral.sh/uv/) or [pipx](https://pipx.pypa.io/):
60
+
61
+ ```sh
62
+ uv tool install agentprof
63
+ # or
64
+ pipx install agentprof
65
+ ```
66
+
67
+ Or run it once without installing it:
68
+
69
+ ```sh
70
+ uvx agentprof
71
+ ```
72
+
73
+ agentprof requires Python 3.12 or newer.
74
+
75
+ ## Usage
76
+
77
+ ```sh
78
+ agentprof
79
+ ```
80
+
81
+ This starts a local server on `127.0.0.1:8765` and opens your browser.
82
+ The session list appears immediately and fills in while sessions are summarised in the background; a session is analysed in full when you open it.
83
+
84
+ ```
85
+ agentprof [SESSION] [--host 127.0.0.1] [--port 8765] [--no-browser]
86
+ [--claude-root DIR] [--codex-root DIR] [--copilot-root DIR]
87
+ [--pricing FILE]
88
+ ```
89
+
90
+ | Option | Purpose |
91
+ |---|---|
92
+ | `SESSION` | Open a session directly: `<agent>:<id>` (e.g. `claude-code:<id>`), a bare id, or a session file path such as a Copilot chat export. |
93
+ | `--host`, `--port` | Interface and port to bind. |
94
+ | `--no-browser` | Do not open a browser. |
95
+ | `--claude-root`, `--codex-root`, `--copilot-root` | Read sessions from a different directory. |
96
+ | `--pricing` | Replace the bundled price table: per-model token prices and the USD value of a Copilot credit (`usd_per_credit`). |
97
+
98
+ ## Supported agents
99
+
100
+ | Agent | Sessions read from | Cost |
101
+ |---|---|---|
102
+ | Claude Code | `~/.claude/projects` (or `$CLAUDE_CONFIG_DIR/projects`), including subagent transcripts | USD at API list prices, estimated |
103
+ | OpenAI Codex CLI | `~/.codex/sessions`, including subagent rollouts | USD at API list prices, estimated |
104
+ | VS Code Copilot Chat | `workspaceStorage` of VS Code and VS Code Insiders on Linux, macOS and Windows | Credits as reported by Copilot, converted to USD at $0.01 per credit |
105
+
106
+ Claude Code and Codex costs are API-equivalent estimates; on a subscription you do not pay per token.
107
+ Costs keep their native unit and are never added across units.
108
+
109
+ ## Findings
110
+
111
+ agentprof flags likely waste as hints, not verdicts.
112
+ Each finding is attached to the turn or agent it is about, and the session header counts them.
113
+
114
+ | Finding | What it looks for |
115
+ |---|---|
116
+ | Repeated reads | The same file read several times with overlapping line ranges. |
117
+ | Re-acquired context | A subagent reading files its parent agent had already read. |
118
+ | Retry chains | Sibling agents started with very similar tasks. |
119
+ | Repeated or failing commands | The same command run again and again, or a high tool failure rate. |
120
+ | Polling loops | Long streaks of consecutive polling calls. |
121
+ | Cost outliers | Agents that cost far more than their siblings. |
122
+ | Context bloat | Large uncached prompts and low cache hit ratios. |
123
+ | Cold cache rewrites | Large cache writes with little reuse, for example after the cache expired during a wait for the user. |
124
+ | Idle parents | A parent agent idling after a child agent completed. |
125
+ | Context jumps | Context that grew sharply between two calls. |
126
+
127
+ ## Local API for AI agents
128
+
129
+ agentprof is useful to people, and just as useful to AI agents.
130
+ While it runs, everything it knows about a session is available as JSON on the same port, so you can point an agent at a session and ask it what went wrong, why a run was expensive or how its subagents worked together.
131
+
132
+ The API is built for this:
133
+
134
+ - **Self-describing**: [`/api`](http://127.0.0.1:8765/api/) lists every endpoint with its parameters, and each session page links to its JSON, so a URL from the browser is enough to start with.
135
+ `/sessions/{id}?format=json` returns the same data as the API route.
136
+ - **Agent by agent**: `/summary` gives one row per agent with its parent agent, so the delegation tree can be rebuilt without the full call tree.
137
+ Each row has the agent's topic, models, LLM calls, peak context, tokens, cache TTL, resumes, longest gap, its own cost and the cost of everything it delegated.
138
+ - **Findings first**: `/findings` puts the likely waste with the highest estimated cost first.
139
+ - **Bounded downloads**: `depth` and `fields` cut a large call tree down to what fits in a context window; prompts, results and tool arguments are only fetched for the node that needs them.
140
+ - **Honest numbers**: every value says whether it is `exact`, `estimated` or `n/a`, so an agent can tell measurements from guesses.
141
+
142
+ For example, ask your agent:
143
+
144
+ ```text
145
+ agentprof is running on http://127.0.0.1:8765. Start at /api, open session
146
+ claude-code:<id> and explain which subagents drove the cost, where they
147
+ waited for each other, and what we could do differently next time.
148
+ ```
149
+
150
+ | Endpoint | Returns |
151
+ |---|---|
152
+ | [`/api`](http://127.0.0.1:8765/api/) | Endpoint index with parameters and descriptions |
153
+ | [`/docs`](http://127.0.0.1:8765/docs) | Interactive OpenAPI schema |
154
+ | `/api/sessions` | All sessions, newest first |
155
+ | `/api/sessions/events` | Server-sent events for session list updates |
156
+ | `/api/sessions/{id}` | The full call tree with metrics and findings; `depth` and `fields=session,diagnostics,tree` bound a large download |
157
+ | `/api/sessions/{id}/summary` | One compact row per agent, with its parent, cost and cache breakdowns |
158
+ | `/api/sessions/{id}/findings` | Findings, ordered by estimated avoidable cost, severity and time |
159
+ | `/api/sessions/{id}/nodes/{node_id}` | Prompt, result and raw tool arguments of one node |
160
+ | `/api/sessions/{id}/diagnostics` | Parse counts and redacted details of malformed lines |
161
+ | `/api/pricing` | The effective price table and its model matching rule |
162
+
163
+ ## Development
164
+
165
+ ```sh
166
+ ./bootstrap.sh # install uv, Node (nvm), pnpm and all dependencies
167
+ uv run agentprof # run against your own sessions
168
+ pnpm --dir frontend dev # frontend dev server, proxies /api to port 8765
169
+ uv run qa # lint, type check and tests for Python and the frontend
170
+ uv run build-dist # build and smoke-test the distributions
171
+ ```
172
+
173
+ See [`docs/architecture.md`](https://github.com/epicodic/agentprof/blob/main/docs/architecture.md) for how the code fits together, [`AGENTS.md`](https://github.com/epicodic/agentprof/blob/main/AGENTS.md) for conventions and [`docs/releasing.md`](https://github.com/epicodic/agentprof/blob/main/docs/releasing.md) for releases.
174
+
175
+ ## License
176
+
177
+ [MIT](https://github.com/epicodic/agentprof/blob/main/LICENSE)
@@ -0,0 +1,152 @@
1
+ # agentprof
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/agentprof?cacheSeconds=3600)](https://pypi.org/project/agentprof/)
4
+ [![Python versions](https://img.shields.io/pypi/pyversions/agentprof?cacheSeconds=3600)](https://pypi.org/project/agentprof/)
5
+ [![CI](https://github.com/epicodic/agentprof/actions/workflows/ci.yml/badge.svg)](https://github.com/epicodic/agentprof/actions/workflows/ci.yml)
6
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](https://github.com/epicodic/agentprof/blob/main/LICENSE)
7
+
8
+ **A profiler for AI coding agents: see where your agents spend time, tokens and money.**
9
+
10
+ agentprof reads the session logs that Claude Code, OpenAI Codex CLI and VS Code Copilot Chat already write on your machine.
11
+ It shows each session as a call tree of turns, subagents and tool calls, with an inline timeline, token counts, context growth, costs and hints about likely waste.
12
+ Everything runs locally, so your sessions never leave your machine.
13
+
14
+ ![A Claude Code session as a call tree with timeline, cost, tokens and context per row](https://media.githubusercontent.com/media/epicodic/agentprof/main/docs/images/session-tree.png)
15
+
16
+ ## Features
17
+
18
+ - **Call tree with timeline**: every prompt, subagent and tool call becomes a row with its duration, cost, tokens and peak context, next to a timeline bar for when it ran.
19
+ Nested subagents get their own colour-coded agent numbers, so you can follow a delegation chain at a glance.
20
+ - **Cost and token accounting**: costs and tokens are given both per node and rolled up per subtree, with input, output, cache read and cache write tokens counted separately.
21
+ Estimated values are marked `≈`, and values the logs do not contain are shown as `–` instead of being guessed.
22
+ - **Context tracking**: see how the context window grows call by call, where it peaks and where it was compacted.
23
+ - **Agent summary**: one row per agent with its model, cache TTL, resumes, duration, own cost, share of the session cost and token breakdown.
24
+ - **Node details**: open any turn or agent to see its timeline, cost per LLM call, context chart, subagents and a searchable list of LLM and tool calls, down to the raw prompt, result and tool arguments.
25
+ - **Waste findings**: hints, not verdicts, about where time and money may have gone (see [Findings](#findings)).
26
+ - **Live updates**: the session list fills in within seconds, and open sessions update while an agent is still working.
27
+ - **JSON API for AI agents**: everything in the UI is also available as compact JSON, so an AI agent can analyse sessions itself, including how the agents and subagents in them worked together.
28
+
29
+ ![Node details with timeline, cost per LLM call, context growth, subagents and LLM calls](https://media.githubusercontent.com/media/epicodic/agentprof/main/docs/images/node-details.png)
30
+
31
+ ## Installation
32
+
33
+ agentprof is a command-line tool that starts a local web app.
34
+ Install it in its own isolated environment with [uv](https://docs.astral.sh/uv/) or [pipx](https://pipx.pypa.io/):
35
+
36
+ ```sh
37
+ uv tool install agentprof
38
+ # or
39
+ pipx install agentprof
40
+ ```
41
+
42
+ Or run it once without installing it:
43
+
44
+ ```sh
45
+ uvx agentprof
46
+ ```
47
+
48
+ agentprof requires Python 3.12 or newer.
49
+
50
+ ## Usage
51
+
52
+ ```sh
53
+ agentprof
54
+ ```
55
+
56
+ This starts a local server on `127.0.0.1:8765` and opens your browser.
57
+ The session list appears immediately and fills in while sessions are summarised in the background; a session is analysed in full when you open it.
58
+
59
+ ```
60
+ agentprof [SESSION] [--host 127.0.0.1] [--port 8765] [--no-browser]
61
+ [--claude-root DIR] [--codex-root DIR] [--copilot-root DIR]
62
+ [--pricing FILE]
63
+ ```
64
+
65
+ | Option | Purpose |
66
+ |---|---|
67
+ | `SESSION` | Open a session directly: `<agent>:<id>` (e.g. `claude-code:<id>`), a bare id, or a session file path such as a Copilot chat export. |
68
+ | `--host`, `--port` | Interface and port to bind. |
69
+ | `--no-browser` | Do not open a browser. |
70
+ | `--claude-root`, `--codex-root`, `--copilot-root` | Read sessions from a different directory. |
71
+ | `--pricing` | Replace the bundled price table: per-model token prices and the USD value of a Copilot credit (`usd_per_credit`). |
72
+
73
+ ## Supported agents
74
+
75
+ | Agent | Sessions read from | Cost |
76
+ |---|---|---|
77
+ | Claude Code | `~/.claude/projects` (or `$CLAUDE_CONFIG_DIR/projects`), including subagent transcripts | USD at API list prices, estimated |
78
+ | OpenAI Codex CLI | `~/.codex/sessions`, including subagent rollouts | USD at API list prices, estimated |
79
+ | VS Code Copilot Chat | `workspaceStorage` of VS Code and VS Code Insiders on Linux, macOS and Windows | Credits as reported by Copilot, converted to USD at $0.01 per credit |
80
+
81
+ Claude Code and Codex costs are API-equivalent estimates; on a subscription you do not pay per token.
82
+ Costs keep their native unit and are never added across units.
83
+
84
+ ## Findings
85
+
86
+ agentprof flags likely waste as hints, not verdicts.
87
+ Each finding is attached to the turn or agent it is about, and the session header counts them.
88
+
89
+ | Finding | What it looks for |
90
+ |---|---|
91
+ | Repeated reads | The same file read several times with overlapping line ranges. |
92
+ | Re-acquired context | A subagent reading files its parent agent had already read. |
93
+ | Retry chains | Sibling agents started with very similar tasks. |
94
+ | Repeated or failing commands | The same command run again and again, or a high tool failure rate. |
95
+ | Polling loops | Long streaks of consecutive polling calls. |
96
+ | Cost outliers | Agents that cost far more than their siblings. |
97
+ | Context bloat | Large uncached prompts and low cache hit ratios. |
98
+ | Cold cache rewrites | Large cache writes with little reuse, for example after the cache expired during a wait for the user. |
99
+ | Idle parents | A parent agent idling after a child agent completed. |
100
+ | Context jumps | Context that grew sharply between two calls. |
101
+
102
+ ## Local API for AI agents
103
+
104
+ agentprof is useful to people, and just as useful to AI agents.
105
+ While it runs, everything it knows about a session is available as JSON on the same port, so you can point an agent at a session and ask it what went wrong, why a run was expensive or how its subagents worked together.
106
+
107
+ The API is built for this:
108
+
109
+ - **Self-describing**: [`/api`](http://127.0.0.1:8765/api/) lists every endpoint with its parameters, and each session page links to its JSON, so a URL from the browser is enough to start with.
110
+ `/sessions/{id}?format=json` returns the same data as the API route.
111
+ - **Agent by agent**: `/summary` gives one row per agent with its parent agent, so the delegation tree can be rebuilt without the full call tree.
112
+ Each row has the agent's topic, models, LLM calls, peak context, tokens, cache TTL, resumes, longest gap, its own cost and the cost of everything it delegated.
113
+ - **Findings first**: `/findings` puts the likely waste with the highest estimated cost first.
114
+ - **Bounded downloads**: `depth` and `fields` cut a large call tree down to what fits in a context window; prompts, results and tool arguments are only fetched for the node that needs them.
115
+ - **Honest numbers**: every value says whether it is `exact`, `estimated` or `n/a`, so an agent can tell measurements from guesses.
116
+
117
+ For example, ask your agent:
118
+
119
+ ```text
120
+ agentprof is running on http://127.0.0.1:8765. Start at /api, open session
121
+ claude-code:<id> and explain which subagents drove the cost, where they
122
+ waited for each other, and what we could do differently next time.
123
+ ```
124
+
125
+ | Endpoint | Returns |
126
+ |---|---|
127
+ | [`/api`](http://127.0.0.1:8765/api/) | Endpoint index with parameters and descriptions |
128
+ | [`/docs`](http://127.0.0.1:8765/docs) | Interactive OpenAPI schema |
129
+ | `/api/sessions` | All sessions, newest first |
130
+ | `/api/sessions/events` | Server-sent events for session list updates |
131
+ | `/api/sessions/{id}` | The full call tree with metrics and findings; `depth` and `fields=session,diagnostics,tree` bound a large download |
132
+ | `/api/sessions/{id}/summary` | One compact row per agent, with its parent, cost and cache breakdowns |
133
+ | `/api/sessions/{id}/findings` | Findings, ordered by estimated avoidable cost, severity and time |
134
+ | `/api/sessions/{id}/nodes/{node_id}` | Prompt, result and raw tool arguments of one node |
135
+ | `/api/sessions/{id}/diagnostics` | Parse counts and redacted details of malformed lines |
136
+ | `/api/pricing` | The effective price table and its model matching rule |
137
+
138
+ ## Development
139
+
140
+ ```sh
141
+ ./bootstrap.sh # install uv, Node (nvm), pnpm and all dependencies
142
+ uv run agentprof # run against your own sessions
143
+ pnpm --dir frontend dev # frontend dev server, proxies /api to port 8765
144
+ uv run qa # lint, type check and tests for Python and the frontend
145
+ uv run build-dist # build and smoke-test the distributions
146
+ ```
147
+
148
+ See [`docs/architecture.md`](https://github.com/epicodic/agentprof/blob/main/docs/architecture.md) for how the code fits together, [`AGENTS.md`](https://github.com/epicodic/agentprof/blob/main/AGENTS.md) for conventions and [`docs/releasing.md`](https://github.com/epicodic/agentprof/blob/main/docs/releasing.md) for releases.
149
+
150
+ ## License
151
+
152
+ [MIT](https://github.com/epicodic/agentprof/blob/main/LICENSE)
@@ -0,0 +1,95 @@
1
+ [project]
2
+ name = "agentprof"
3
+ version = "0.1.0"
4
+ description = "Analyse AI coding agent sessions: call trees, timings, tokens, cost and waste."
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ license-files = ["LICENSE"]
8
+ requires-python = ">=3.12"
9
+ keywords = [
10
+ "ai",
11
+ "agents",
12
+ "copilot",
13
+ "claude-code",
14
+ "llm",
15
+ "tokens",
16
+ "cost",
17
+ "observability",
18
+ ]
19
+ classifiers = [
20
+ "Development Status :: 3 - Alpha",
21
+ "Environment :: Web Environment",
22
+ "Intended Audience :: Developers",
23
+ "Operating System :: OS Independent",
24
+ "Programming Language :: Python :: 3",
25
+ "Programming Language :: Python :: 3.12",
26
+ "Programming Language :: Python :: 3.13",
27
+ "Programming Language :: Python :: 3.14",
28
+ "Topic :: Software Development :: Quality Assurance",
29
+ ]
30
+ dependencies = [
31
+ "fastapi>=0.120",
32
+ "uvicorn>=0.38",
33
+ ]
34
+
35
+ [[project.authors]]
36
+ name = "epicodic"
37
+
38
+ [project.scripts]
39
+ agentprof = "agentprof.cli:main"
40
+
41
+ [project.urls]
42
+ Homepage = "https://github.com/epicodic/agentprof"
43
+ Repository = "https://github.com/epicodic/agentprof"
44
+ Issues = "https://github.com/epicodic/agentprof/issues"
45
+
46
+ [project.entry-points."agentprof.adapters"]
47
+ claude-code = "agentprof.adapters.claude_code.adapter:ClaudeCodeAdapter"
48
+ codex = "agentprof.adapters.codex.adapter:CodexAdapter"
49
+ copilot-vscode = "agentprof.adapters.copilot_vscode.adapter:CopilotVscodeAdapter"
50
+
51
+ [build-system]
52
+ requires = ["uv_build>=0.11.6,<0.12"]
53
+ build-backend = "uv_build"
54
+
55
+ [dependency-groups]
56
+ dev = [
57
+ "agentprof-qa",
58
+ "httpx2>=2.13",
59
+ "pytest>=8.3",
60
+ "ruff>=0.16.8",
61
+ "ty>=0.0.83",
62
+ ]
63
+
64
+ [tool.uv.workspace]
65
+ members = ["tools/qa"]
66
+
67
+ [tool.uv.sources.agentprof-qa]
68
+ workspace = true
69
+
70
+ [tool.ruff]
71
+ line-length = 120
72
+ target-version = "py312"
73
+ src = [
74
+ "src",
75
+ "tests",
76
+ "tools/qa/src",
77
+ ]
78
+ extend-exclude = [
79
+ "docs",
80
+ ".agents",
81
+ ]
82
+
83
+ [tool.ruff.lint]
84
+ select = [
85
+ "E",
86
+ "F",
87
+ "I",
88
+ "UP",
89
+ "B",
90
+ "SIM",
91
+ ]
92
+
93
+ [tool.pytest.ini_options]
94
+ testpaths = ["tests"]
95
+ addopts = ["--import-mode=importlib"]
@@ -0,0 +1,67 @@
1
+ [project]
2
+ name = "agentprof"
3
+ version = "0.1.0"
4
+ description = "Analyse AI coding agent sessions: call trees, timings, tokens, cost and waste."
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ license-files = ["LICENSE"]
8
+ requires-python = ">=3.12"
9
+ authors = [{ name = "epicodic" }]
10
+ keywords = ["ai", "agents", "copilot", "claude-code", "llm", "tokens", "cost", "observability"]
11
+ classifiers = [
12
+ "Development Status :: 3 - Alpha",
13
+ "Environment :: Web Environment",
14
+ "Intended Audience :: Developers",
15
+ "Operating System :: OS Independent",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.12",
18
+ "Programming Language :: Python :: 3.13",
19
+ "Programming Language :: Python :: 3.14",
20
+ "Topic :: Software Development :: Quality Assurance",
21
+ ]
22
+ dependencies = ["fastapi>=0.120", "uvicorn>=0.38"]
23
+
24
+ [project.scripts]
25
+ agentprof = "agentprof.cli:main"
26
+
27
+ [project.urls]
28
+ Homepage = "https://github.com/epicodic/agentprof"
29
+ Repository = "https://github.com/epicodic/agentprof"
30
+ Issues = "https://github.com/epicodic/agentprof/issues"
31
+
32
+ [project.entry-points."agentprof.adapters"]
33
+ claude-code = "agentprof.adapters.claude_code.adapter:ClaudeCodeAdapter"
34
+ codex = "agentprof.adapters.codex.adapter:CodexAdapter"
35
+ copilot-vscode = "agentprof.adapters.copilot_vscode.adapter:CopilotVscodeAdapter"
36
+
37
+ [build-system]
38
+ requires = ["uv_build>=0.11.6,<0.12"]
39
+ build-backend = "uv_build"
40
+
41
+ [dependency-groups]
42
+ dev = [
43
+ "agentprof-qa",
44
+ "httpx2>=2.13",
45
+ "pytest>=8.3",
46
+ "ruff>=0.16.8",
47
+ "ty>=0.0.83",
48
+ ]
49
+
50
+ [tool.uv.workspace]
51
+ members = ["tools/qa"]
52
+
53
+ [tool.uv.sources]
54
+ agentprof-qa = { workspace = true }
55
+
56
+ [tool.ruff]
57
+ line-length = 120
58
+ target-version = "py312"
59
+ src = ["src", "tests", "tools/qa/src"]
60
+ extend-exclude = ["docs", ".agents"]
61
+
62
+ [tool.ruff.lint]
63
+ select = ["E", "F", "I", "UP", "B", "SIM"]
64
+
65
+ [tool.pytest.ini_options]
66
+ testpaths = ["tests"]
67
+ addopts = ["--import-mode=importlib"]
@@ -0,0 +1,7 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2026 epicodic
3
+ """agentprof: analyse AI coding agent sessions."""
4
+
5
+ from importlib.metadata import version
6
+
7
+ __version__ = version("agentprof")
@@ -0,0 +1,15 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2026 epicodic
3
+ """Agent adapters: turn agent-specific session files into the neutral model."""
4
+
5
+ from importlib.metadata import entry_points
6
+
7
+ from agentprof.adapters.base import AdapterConfig, AgentAdapter
8
+
9
+ ENTRY_POINT_GROUP = "agentprof.adapters"
10
+
11
+
12
+ def load_adapters(config: AdapterConfig) -> list[AgentAdapter]:
13
+ """Instantiate every adapter registered under the `agentprof.adapters` entry point group."""
14
+ registered = sorted(entry_points(group=ENTRY_POINT_GROUP), key=lambda entry_point: entry_point.name)
15
+ return [entry_point.load()(config) for entry_point in registered]
@@ -0,0 +1,79 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2026 epicodic
3
+ """The adapter protocol and the lightweight types the registry works with."""
4
+
5
+ from collections.abc import Iterable
6
+ from dataclasses import dataclass, field
7
+ from pathlib import Path
8
+ from typing import Protocol
9
+
10
+ from agentprof.model import CostMetric, Session
11
+
12
+
13
+ def latest_mtime(paths: Iterable[Path]) -> float:
14
+ """The newest modification time among `paths`; paths that vanished meanwhile are ignored."""
15
+ times: list[float] = []
16
+ for path in paths:
17
+ try:
18
+ times.append(path.stat().st_mtime)
19
+ except OSError:
20
+ continue
21
+ return max(times, default=0.0)
22
+
23
+
24
+ @dataclass(frozen=True)
25
+ class AdapterConfig:
26
+ """User configuration shared by all adapters.
27
+
28
+ `roots` maps an adapter name to an overriding data root; `pricing_file` replaces the bundled price table.
29
+ """
30
+
31
+ roots: dict[str, Path] = field(default_factory=dict)
32
+ pricing_file: Path | None = None
33
+
34
+
35
+ @dataclass(frozen=True)
36
+ class SessionRef:
37
+ """A cheap handle to one session file."""
38
+
39
+ agent: str
40
+ native_id: str
41
+ path: Path
42
+ mtime: float
43
+
44
+ @property
45
+ def id(self) -> str:
46
+ return f"{self.agent}:{self.native_id}"
47
+
48
+
49
+ @dataclass
50
+ class SessionSummary:
51
+ """One row of the session list: only what an adapter can read without building the tree."""
52
+
53
+ id: str
54
+ agent: str
55
+ title: str
56
+ workspace: str | None
57
+ start_ms: float | None
58
+ end_ms: float | None
59
+ file_size: int
60
+ last_activity_ms: float | None = None
61
+ cost_total: CostMetric = field(default_factory=CostMetric.not_available)
62
+
63
+
64
+ class AgentAdapter(Protocol):
65
+ """Turns one agent's session files into the neutral model.
66
+
67
+ Implementations are constructed with an `AdapterConfig` and registered under the entry point group
68
+ `agentprof.adapters`. `summarize` and `analyze` raise on sessions they cannot read.
69
+ """
70
+
71
+ name: str
72
+
73
+ def discover(self) -> Iterable[SessionRef]: ...
74
+
75
+ def open_path(self, path: Path) -> SessionRef | None: ...
76
+
77
+ def summarize(self, ref: SessionRef) -> SessionSummary: ...
78
+
79
+ def analyze(self, ref: SessionRef) -> Session: ...
@@ -0,0 +1,3 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2026 epicodic
3
+ """Claude Code adapter."""