Initial public upload from Projekte/Codex_Usage_Profil
Browse files- .codex.pre-coding-mcp-20260908T010027 +0 -0
- .codex/config.toml +31 -0
- .gitignore +3 -0
- README.md +51 -0
- codex_usage_profiler/__init__.py +5 -0
- codex_usage_profiler/__main__.py +4 -0
- codex_usage_profiler/cli.py +82 -0
- codex_usage_profiler/core.py +411 -0
- codex_usage_profiler/render.py +436 -0
- pyproject.toml +17 -0
- reports-last7/codex-usage.md +99 -0
- reports/codex-usage.html +148 -0
- reports/codex-usage.md +234 -0
- tests/test_profiler.py +296 -0
.codex.pre-coding-mcp-20260908T010027
ADDED
|
File without changes
|
.codex/config.toml
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Coding MCPs: project-local registration (2026-09-07).
|
| 2 |
+
|
| 3 |
+
[mcp_servers.serena]
|
| 4 |
+
command = "/home/smlflg/.local/share/coding-mcp/serena/.venv/bin/serena"
|
| 5 |
+
args = ["start-mcp-server", "--context=codex", "--project", "/home/smlflg/Projekte/Codex_Usage_Profil", "--enable-web-dashboard", "false", "--open-web-dashboard", "false", "--enable-gui-log-window", "false"]
|
| 6 |
+
cwd = "/home/smlflg/Projekte/Codex_Usage_Profil"
|
| 7 |
+
enabled = true
|
| 8 |
+
startup_timeout_sec = 120
|
| 9 |
+
tool_timeout_sec = 180
|
| 10 |
+
|
| 11 |
+
[mcp_servers.serena.env]
|
| 12 |
+
"SERENA_HOME" = "/home/smlflg/.local/share/coding-mcp/serena/state"
|
| 13 |
+
|
| 14 |
+
[mcp_servers.gitnexus]
|
| 15 |
+
command = "/home/smlflg/.nvm/versions/node/v24.13.0/bin/node"
|
| 16 |
+
args = ["/home/smlflg/.local/share/coding-mcp/gitnexus/node_modules/gitnexus/dist/cli/index.js", "mcp"]
|
| 17 |
+
cwd = "/home/smlflg/Projekte/Codex_Usage_Profil"
|
| 18 |
+
enabled = true
|
| 19 |
+
startup_timeout_sec = 120
|
| 20 |
+
tool_timeout_sec = 180
|
| 21 |
+
|
| 22 |
+
[mcp_servers.gitnexus.env]
|
| 23 |
+
"GITNEXUS_HOME" = "/home/smlflg/.local/share/coding-mcp/gitnexus/runtime"
|
| 24 |
+
|
| 25 |
+
[mcp_servers.context7]
|
| 26 |
+
command = "/home/smlflg/.nvm/versions/node/v24.13.0/bin/node"
|
| 27 |
+
args = ["/home/smlflg/.local/share/coding-mcp/context7/node_modules/@upstash/context7-mcp/dist/index.js"]
|
| 28 |
+
cwd = "/home/smlflg/Projekte/Codex_Usage_Profil"
|
| 29 |
+
enabled = true
|
| 30 |
+
startup_timeout_sec = 120
|
| 31 |
+
tool_timeout_sec = 180
|
.gitignore
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__pycache__/
|
| 2 |
+
*.py[cod]
|
| 3 |
+
.pytest_cache/
|
README.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Codex Usage Profiler
|
| 2 |
+
|
| 3 |
+
Local CLI for summarizing Codex usage from `~/.codex/state_5.sqlite` and rollout
|
| 4 |
+
JSONL files.
|
| 5 |
+
|
| 6 |
+
It reports:
|
| 7 |
+
|
| 8 |
+
- daily and ISO-week token totals
|
| 9 |
+
- tokens by cwd, model, role, and main vs subagent
|
| 10 |
+
- top sessions
|
| 11 |
+
- optional rollout token breakdowns for input, cached input, output, and
|
| 12 |
+
reasoning tokens when those events exist
|
| 13 |
+
- Markdown and static HTML output
|
| 14 |
+
|
| 15 |
+
## Usage
|
| 16 |
+
|
| 17 |
+
```bash
|
| 18 |
+
python3 -m codex_usage_profiler
|
| 19 |
+
```
|
| 20 |
+
|
| 21 |
+
Default output is written to:
|
| 22 |
+
|
| 23 |
+
- `reports/codex-usage.md`
|
| 24 |
+
- `reports/codex-usage.html`
|
| 25 |
+
|
| 26 |
+
Useful options:
|
| 27 |
+
|
| 28 |
+
```bash
|
| 29 |
+
python3 -m codex_usage_profiler \
|
| 30 |
+
--state ~/.codex/state_5.sqlite \
|
| 31 |
+
--sessions-dir ~/.codex/sessions \
|
| 32 |
+
--out reports \
|
| 33 |
+
--format both \
|
| 34 |
+
--tz Europe/Berlin \
|
| 35 |
+
--days 30 \
|
| 36 |
+
--top 25
|
| 37 |
+
```
|
| 38 |
+
|
| 39 |
+
`--days N` includes the last `N` local calendar days including today. Week
|
| 40 |
+
buckets use ISO weeks, starting on Monday.
|
| 41 |
+
|
| 42 |
+
The report never includes raw prompts, messages, command output, or model
|
| 43 |
+
responses. It only uses metadata and token counters.
|
| 44 |
+
|
| 45 |
+
## Development
|
| 46 |
+
|
| 47 |
+
Run tests with:
|
| 48 |
+
|
| 49 |
+
```bash
|
| 50 |
+
python3 -m unittest discover -s tests
|
| 51 |
+
```
|
codex_usage_profiler/__init__.py
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Local Codex usage profiler."""
|
| 2 |
+
|
| 3 |
+
from .core import build_report
|
| 4 |
+
|
| 5 |
+
__all__ = ["build_report"]
|
codex_usage_profiler/__main__.py
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .cli import main
|
| 2 |
+
|
| 3 |
+
if __name__ == "__main__":
|
| 4 |
+
raise SystemExit(main())
|
codex_usage_profiler/cli.py
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
import argparse
|
| 4 |
+
import os
|
| 5 |
+
from pathlib import Path
|
| 6 |
+
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
|
| 7 |
+
|
| 8 |
+
from .core import build_report
|
| 9 |
+
from .render import write_reports
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def main(argv: list[str] | None = None) -> int:
|
| 13 |
+
parser = _build_parser()
|
| 14 |
+
args = parser.parse_args(argv)
|
| 15 |
+
|
| 16 |
+
try:
|
| 17 |
+
ZoneInfo(args.tz)
|
| 18 |
+
except ZoneInfoNotFoundError:
|
| 19 |
+
parser.error(f"unknown timezone: {args.tz}")
|
| 20 |
+
|
| 21 |
+
report = build_report(
|
| 22 |
+
state_path=Path(args.state).expanduser(),
|
| 23 |
+
sessions_dir=Path(args.sessions_dir).expanduser(),
|
| 24 |
+
tz_name=args.tz,
|
| 25 |
+
days=args.days,
|
| 26 |
+
top=args.top,
|
| 27 |
+
)
|
| 28 |
+
written = write_reports(report, Path(args.out).expanduser(), args.format)
|
| 29 |
+
|
| 30 |
+
for path in written:
|
| 31 |
+
print(f"Wrote {path}")
|
| 32 |
+
print(f"Sessions: {len(report.sessions):,}")
|
| 33 |
+
print(f"Total tokens: {report.total_tokens:,}")
|
| 34 |
+
if report.warnings:
|
| 35 |
+
print(f"Warnings: {len(report.warnings):,}")
|
| 36 |
+
return 0
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def _build_parser() -> argparse.ArgumentParser:
|
| 40 |
+
parser = argparse.ArgumentParser(
|
| 41 |
+
prog="codex-usage-profiler",
|
| 42 |
+
description="Summarize local Codex usage from state_5.sqlite and rollout JSONL files.",
|
| 43 |
+
)
|
| 44 |
+
parser.add_argument(
|
| 45 |
+
"--state",
|
| 46 |
+
default="~/.codex/state_5.sqlite",
|
| 47 |
+
help="Path to Codex state_5.sqlite. Default: %(default)s",
|
| 48 |
+
)
|
| 49 |
+
parser.add_argument(
|
| 50 |
+
"--sessions-dir",
|
| 51 |
+
default="~/.codex/sessions",
|
| 52 |
+
help="Root directory containing rollout JSONL files. Default: %(default)s",
|
| 53 |
+
)
|
| 54 |
+
parser.add_argument(
|
| 55 |
+
"--out",
|
| 56 |
+
default="reports",
|
| 57 |
+
help="Output directory. Default: %(default)s",
|
| 58 |
+
)
|
| 59 |
+
parser.add_argument(
|
| 60 |
+
"--format",
|
| 61 |
+
choices=["md", "html", "both"],
|
| 62 |
+
default="both",
|
| 63 |
+
help="Report format to write. Default: %(default)s",
|
| 64 |
+
)
|
| 65 |
+
parser.add_argument(
|
| 66 |
+
"--tz",
|
| 67 |
+
default=os.environ.get("TZ", "Europe/Berlin"),
|
| 68 |
+
help="Timezone for day/week grouping. Default: %(default)s",
|
| 69 |
+
)
|
| 70 |
+
parser.add_argument(
|
| 71 |
+
"--days",
|
| 72 |
+
type=int,
|
| 73 |
+
default=None,
|
| 74 |
+
help="Include the last N local calendar days including today.",
|
| 75 |
+
)
|
| 76 |
+
parser.add_argument(
|
| 77 |
+
"--top",
|
| 78 |
+
type=int,
|
| 79 |
+
default=20,
|
| 80 |
+
help="Number of top sessions to include. Default: %(default)s",
|
| 81 |
+
)
|
| 82 |
+
return parser
|
codex_usage_profiler/core.py
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
import json
|
| 4 |
+
import sqlite3
|
| 5 |
+
from collections import defaultdict
|
| 6 |
+
from dataclasses import dataclass, field
|
| 7 |
+
from datetime import datetime, timedelta, timezone
|
| 8 |
+
from pathlib import Path
|
| 9 |
+
from typing import Any, Callable, Iterable
|
| 10 |
+
from urllib.parse import quote
|
| 11 |
+
from zoneinfo import ZoneInfo
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
@dataclass(slots=True)
|
| 15 |
+
class TokenBreakdown:
|
| 16 |
+
input_tokens: int = 0
|
| 17 |
+
cached_input_tokens: int = 0
|
| 18 |
+
output_tokens: int = 0
|
| 19 |
+
reasoning_output_tokens: int = 0
|
| 20 |
+
total_tokens: int = 0
|
| 21 |
+
|
| 22 |
+
@classmethod
|
| 23 |
+
def from_usage(cls, usage: dict[str, Any]) -> "TokenBreakdown":
|
| 24 |
+
return cls(
|
| 25 |
+
input_tokens=_int_value(usage.get("input_tokens")),
|
| 26 |
+
cached_input_tokens=_int_value(usage.get("cached_input_tokens")),
|
| 27 |
+
output_tokens=_int_value(usage.get("output_tokens")),
|
| 28 |
+
reasoning_output_tokens=_int_value(usage.get("reasoning_output_tokens")),
|
| 29 |
+
total_tokens=_int_value(usage.get("total_tokens")),
|
| 30 |
+
)
|
| 31 |
+
|
| 32 |
+
def add(self, other: "TokenBreakdown | None") -> None:
|
| 33 |
+
if other is None:
|
| 34 |
+
return
|
| 35 |
+
self.input_tokens += other.input_tokens
|
| 36 |
+
self.cached_input_tokens += other.cached_input_tokens
|
| 37 |
+
self.output_tokens += other.output_tokens
|
| 38 |
+
self.reasoning_output_tokens += other.reasoning_output_tokens
|
| 39 |
+
self.total_tokens += other.total_tokens
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
@dataclass(slots=True)
|
| 43 |
+
class RolloutStats:
|
| 44 |
+
path: Path | None
|
| 45 |
+
found: bool
|
| 46 |
+
token_breakdown: TokenBreakdown | None = None
|
| 47 |
+
model: str | None = None
|
| 48 |
+
cwd: str | None = None
|
| 49 |
+
turn_count: int = 0
|
| 50 |
+
malformed_lines: int = 0
|
| 51 |
+
warnings: list[str] = field(default_factory=list)
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
@dataclass(slots=True)
|
| 55 |
+
class SessionUsage:
|
| 56 |
+
thread_id: str
|
| 57 |
+
created_at: datetime
|
| 58 |
+
updated_at: datetime
|
| 59 |
+
cwd: str
|
| 60 |
+
model: str
|
| 61 |
+
model_provider: str
|
| 62 |
+
role: str
|
| 63 |
+
agent_role: str
|
| 64 |
+
agent_nickname: str
|
| 65 |
+
kind: str
|
| 66 |
+
parent_thread_id: str | None
|
| 67 |
+
title: str
|
| 68 |
+
tokens: int
|
| 69 |
+
rollout_path: Path | None
|
| 70 |
+
rollout_found: bool
|
| 71 |
+
rollout_breakdown: TokenBreakdown | None
|
| 72 |
+
turn_count: int
|
| 73 |
+
|
| 74 |
+
@property
|
| 75 |
+
def week_label(self) -> str:
|
| 76 |
+
year, week, _ = self.created_at.isocalendar()
|
| 77 |
+
return f"{year}-W{week:02d}"
|
| 78 |
+
|
| 79 |
+
@property
|
| 80 |
+
def day_label(self) -> str:
|
| 81 |
+
return self.created_at.date().isoformat()
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
@dataclass(slots=True)
|
| 85 |
+
class Bucket:
|
| 86 |
+
label: str
|
| 87 |
+
sessions: int = 0
|
| 88 |
+
tokens: int = 0
|
| 89 |
+
rollout: TokenBreakdown = field(default_factory=TokenBreakdown)
|
| 90 |
+
|
| 91 |
+
def add(self, session: SessionUsage) -> None:
|
| 92 |
+
self.sessions += 1
|
| 93 |
+
self.tokens += session.tokens
|
| 94 |
+
self.rollout.add(session.rollout_breakdown)
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
@dataclass(slots=True)
|
| 98 |
+
class UsageReport:
|
| 99 |
+
generated_at: datetime
|
| 100 |
+
timezone_name: str
|
| 101 |
+
state_path: Path
|
| 102 |
+
sessions_dir: Path
|
| 103 |
+
sessions: list[SessionUsage]
|
| 104 |
+
daily: list[Bucket]
|
| 105 |
+
weekly: list[Bucket]
|
| 106 |
+
by_cwd: list[Bucket]
|
| 107 |
+
by_model: list[Bucket]
|
| 108 |
+
by_role: list[Bucket]
|
| 109 |
+
by_kind: list[Bucket]
|
| 110 |
+
top_sessions: list[SessionUsage]
|
| 111 |
+
rollout_totals: TokenBreakdown
|
| 112 |
+
warnings: list[str]
|
| 113 |
+
days_filter: int | None = None
|
| 114 |
+
|
| 115 |
+
@property
|
| 116 |
+
def total_tokens(self) -> int:
|
| 117 |
+
return sum(session.tokens for session in self.sessions)
|
| 118 |
+
|
| 119 |
+
@property
|
| 120 |
+
def parsed_rollout_count(self) -> int:
|
| 121 |
+
return sum(1 for session in self.sessions if session.rollout_breakdown is not None)
|
| 122 |
+
|
| 123 |
+
@property
|
| 124 |
+
def missing_rollout_count(self) -> int:
|
| 125 |
+
return sum(1 for session in self.sessions if not session.rollout_found)
|
| 126 |
+
|
| 127 |
+
@property
|
| 128 |
+
def date_range_label(self) -> str:
|
| 129 |
+
if not self.sessions:
|
| 130 |
+
return "n/a"
|
| 131 |
+
first = min(session.created_at for session in self.sessions)
|
| 132 |
+
last = max(session.created_at for session in self.sessions)
|
| 133 |
+
return f"{first.date().isoformat()} to {last.date().isoformat()}"
|
| 134 |
+
|
| 135 |
+
|
| 136 |
+
def build_report(
|
| 137 |
+
*,
|
| 138 |
+
state_path: Path,
|
| 139 |
+
sessions_dir: Path,
|
| 140 |
+
tz_name: str,
|
| 141 |
+
days: int | None = None,
|
| 142 |
+
top: int = 20,
|
| 143 |
+
now: datetime | None = None,
|
| 144 |
+
) -> UsageReport:
|
| 145 |
+
tz = ZoneInfo(tz_name)
|
| 146 |
+
generated_at = (now or datetime.now(tz)).astimezone(tz)
|
| 147 |
+
rows, child_to_parent = _load_threads(state_path)
|
| 148 |
+
sessions: list[SessionUsage] = []
|
| 149 |
+
warnings: list[str] = []
|
| 150 |
+
|
| 151 |
+
if days is not None and days <= 0:
|
| 152 |
+
raise ValueError("--days must be greater than zero")
|
| 153 |
+
cutoff_date = None
|
| 154 |
+
if days is not None:
|
| 155 |
+
cutoff_date = generated_at.date() - timedelta(days=days - 1)
|
| 156 |
+
|
| 157 |
+
for row in rows:
|
| 158 |
+
created_at = _local_datetime(row.get("created_at_ms"), row.get("created_at"), tz)
|
| 159 |
+
if cutoff_date is not None and created_at.date() < cutoff_date:
|
| 160 |
+
continue
|
| 161 |
+
|
| 162 |
+
updated_at = _local_datetime(row.get("updated_at_ms"), row.get("updated_at"), tz)
|
| 163 |
+
thread_id = str(row["id"])
|
| 164 |
+
rollout_path = _resolve_rollout_path(row.get("rollout_path"), sessions_dir, thread_id)
|
| 165 |
+
rollout = parse_rollout(rollout_path)
|
| 166 |
+
warnings.extend(rollout.warnings)
|
| 167 |
+
|
| 168 |
+
parent_thread_id = child_to_parent.get(thread_id)
|
| 169 |
+
kind = "subagent" if parent_thread_id else "main"
|
| 170 |
+
agent_role = str(row.get("agent_role") or "")
|
| 171 |
+
role = agent_role or ("main" if kind == "main" else "unknown")
|
| 172 |
+
model_provider = str(row.get("model_provider") or "unknown")
|
| 173 |
+
model = str(row.get("model") or rollout.model or "unknown")
|
| 174 |
+
cwd = str(row.get("cwd") or rollout.cwd or "unknown")
|
| 175 |
+
|
| 176 |
+
sessions.append(
|
| 177 |
+
SessionUsage(
|
| 178 |
+
thread_id=thread_id,
|
| 179 |
+
created_at=created_at,
|
| 180 |
+
updated_at=updated_at,
|
| 181 |
+
cwd=cwd,
|
| 182 |
+
model=model,
|
| 183 |
+
model_provider=model_provider,
|
| 184 |
+
role=role,
|
| 185 |
+
agent_role=agent_role,
|
| 186 |
+
agent_nickname=str(row.get("agent_nickname") or ""),
|
| 187 |
+
kind=kind,
|
| 188 |
+
parent_thread_id=parent_thread_id,
|
| 189 |
+
title=str(row.get("title") or ""),
|
| 190 |
+
tokens=_int_value(row.get("tokens_used")),
|
| 191 |
+
rollout_path=rollout.path,
|
| 192 |
+
rollout_found=rollout.found,
|
| 193 |
+
rollout_breakdown=rollout.token_breakdown,
|
| 194 |
+
turn_count=rollout.turn_count,
|
| 195 |
+
)
|
| 196 |
+
)
|
| 197 |
+
|
| 198 |
+
sessions.sort(key=lambda session: (session.created_at, session.thread_id))
|
| 199 |
+
rollout_totals = TokenBreakdown()
|
| 200 |
+
for session in sessions:
|
| 201 |
+
rollout_totals.add(session.rollout_breakdown)
|
| 202 |
+
|
| 203 |
+
return UsageReport(
|
| 204 |
+
generated_at=generated_at,
|
| 205 |
+
timezone_name=tz_name,
|
| 206 |
+
state_path=Path(state_path).expanduser(),
|
| 207 |
+
sessions_dir=Path(sessions_dir).expanduser(),
|
| 208 |
+
sessions=sessions,
|
| 209 |
+
daily=_group_sessions(sessions, lambda session: session.day_label, sort_by_label=True),
|
| 210 |
+
weekly=_group_sessions(sessions, lambda session: session.week_label, sort_by_label=True),
|
| 211 |
+
by_cwd=_group_sessions(sessions, lambda session: _compact_path(session.cwd)),
|
| 212 |
+
by_model=_group_sessions(sessions, lambda session: session.model or "unknown"),
|
| 213 |
+
by_role=_group_sessions(sessions, lambda session: session.role or "unknown"),
|
| 214 |
+
by_kind=_group_sessions(sessions, lambda session: session.kind),
|
| 215 |
+
top_sessions=sorted(sessions, key=lambda session: session.tokens, reverse=True)[:top],
|
| 216 |
+
rollout_totals=rollout_totals,
|
| 217 |
+
warnings=warnings,
|
| 218 |
+
days_filter=days,
|
| 219 |
+
)
|
| 220 |
+
|
| 221 |
+
|
| 222 |
+
def parse_rollout(path: Path | None) -> RolloutStats:
|
| 223 |
+
if path is None:
|
| 224 |
+
return RolloutStats(path=None, found=False, warnings=["No rollout path for a session"])
|
| 225 |
+
|
| 226 |
+
expanded = path.expanduser()
|
| 227 |
+
if not expanded.exists():
|
| 228 |
+
return RolloutStats(
|
| 229 |
+
path=expanded,
|
| 230 |
+
found=False,
|
| 231 |
+
warnings=[f"Missing rollout file: {expanded}"],
|
| 232 |
+
)
|
| 233 |
+
|
| 234 |
+
stats = RolloutStats(path=expanded, found=True)
|
| 235 |
+
try:
|
| 236 |
+
with expanded.open("r", encoding="utf-8") as handle:
|
| 237 |
+
for line_number, line in enumerate(handle, start=1):
|
| 238 |
+
if not line.strip():
|
| 239 |
+
continue
|
| 240 |
+
try:
|
| 241 |
+
event = json.loads(line)
|
| 242 |
+
except json.JSONDecodeError:
|
| 243 |
+
stats.malformed_lines += 1
|
| 244 |
+
continue
|
| 245 |
+
_read_rollout_event(stats, event)
|
| 246 |
+
except OSError as exc:
|
| 247 |
+
stats.found = False
|
| 248 |
+
stats.warnings.append(f"Could not read rollout file {expanded}: {exc}")
|
| 249 |
+
return stats
|
| 250 |
+
|
| 251 |
+
if stats.malformed_lines:
|
| 252 |
+
stats.warnings.append(
|
| 253 |
+
f"Malformed JSONL lines in {expanded}: {stats.malformed_lines}"
|
| 254 |
+
)
|
| 255 |
+
return stats
|
| 256 |
+
|
| 257 |
+
|
| 258 |
+
def _read_rollout_event(stats: RolloutStats, event: dict[str, Any]) -> None:
|
| 259 |
+
event_type = event.get("type")
|
| 260 |
+
payload = event.get("payload")
|
| 261 |
+
if not isinstance(payload, dict):
|
| 262 |
+
payload = {}
|
| 263 |
+
|
| 264 |
+
if event_type == "session_meta":
|
| 265 |
+
stats.cwd = stats.cwd or _string_or_none(payload.get("cwd"))
|
| 266 |
+
return
|
| 267 |
+
|
| 268 |
+
if event_type == "turn_context":
|
| 269 |
+
stats.model = stats.model or _string_or_none(payload.get("model"))
|
| 270 |
+
stats.cwd = stats.cwd or _string_or_none(payload.get("cwd"))
|
| 271 |
+
return
|
| 272 |
+
|
| 273 |
+
if event_type != "event_msg":
|
| 274 |
+
return
|
| 275 |
+
|
| 276 |
+
payload_type = payload.get("type")
|
| 277 |
+
if payload_type == "task_started":
|
| 278 |
+
stats.turn_count += 1
|
| 279 |
+
return
|
| 280 |
+
if payload_type != "token_count":
|
| 281 |
+
return
|
| 282 |
+
|
| 283 |
+
info = payload.get("info")
|
| 284 |
+
if not isinstance(info, dict):
|
| 285 |
+
return
|
| 286 |
+
usage = info.get("total_token_usage")
|
| 287 |
+
if isinstance(usage, dict):
|
| 288 |
+
stats.token_breakdown = TokenBreakdown.from_usage(usage)
|
| 289 |
+
|
| 290 |
+
|
| 291 |
+
def _load_threads(state_path: Path) -> tuple[list[dict[str, Any]], dict[str, str]]:
|
| 292 |
+
expanded = Path(state_path).expanduser()
|
| 293 |
+
if not expanded.exists():
|
| 294 |
+
raise FileNotFoundError(f"State database not found: {expanded}")
|
| 295 |
+
|
| 296 |
+
uri = f"file:{quote(str(expanded), safe='/')}?mode=ro"
|
| 297 |
+
with sqlite3.connect(uri, uri=True) as conn:
|
| 298 |
+
conn.row_factory = sqlite3.Row
|
| 299 |
+
conn.execute("PRAGMA query_only = ON")
|
| 300 |
+
rows = [
|
| 301 |
+
dict(row)
|
| 302 |
+
for row in conn.execute(
|
| 303 |
+
"""
|
| 304 |
+
SELECT
|
| 305 |
+
id,
|
| 306 |
+
rollout_path,
|
| 307 |
+
created_at,
|
| 308 |
+
updated_at,
|
| 309 |
+
created_at_ms,
|
| 310 |
+
updated_at_ms,
|
| 311 |
+
model_provider,
|
| 312 |
+
cwd,
|
| 313 |
+
title,
|
| 314 |
+
tokens_used,
|
| 315 |
+
agent_nickname,
|
| 316 |
+
agent_role,
|
| 317 |
+
model
|
| 318 |
+
FROM threads
|
| 319 |
+
ORDER BY created_at_ms ASC, id ASC
|
| 320 |
+
"""
|
| 321 |
+
)
|
| 322 |
+
]
|
| 323 |
+
edges = [
|
| 324 |
+
dict(edge)
|
| 325 |
+
for edge in conn.execute(
|
| 326 |
+
"""
|
| 327 |
+
SELECT parent_thread_id, child_thread_id
|
| 328 |
+
FROM thread_spawn_edges
|
| 329 |
+
"""
|
| 330 |
+
)
|
| 331 |
+
]
|
| 332 |
+
return rows, {str(edge["child_thread_id"]): str(edge["parent_thread_id"]) for edge in edges}
|
| 333 |
+
|
| 334 |
+
|
| 335 |
+
def _resolve_rollout_path(
|
| 336 |
+
rollout_path: Any, sessions_dir: Path, thread_id: str
|
| 337 |
+
) -> Path | None:
|
| 338 |
+
sessions_root = Path(sessions_dir).expanduser()
|
| 339 |
+
if rollout_path:
|
| 340 |
+
candidate = Path(str(rollout_path)).expanduser()
|
| 341 |
+
if not candidate.is_absolute():
|
| 342 |
+
candidate = sessions_root / candidate
|
| 343 |
+
if candidate.exists():
|
| 344 |
+
return candidate
|
| 345 |
+
|
| 346 |
+
if sessions_root.exists():
|
| 347 |
+
matches = sorted(sessions_root.rglob(f"*{thread_id}.jsonl"))
|
| 348 |
+
if matches:
|
| 349 |
+
return matches[0]
|
| 350 |
+
|
| 351 |
+
if rollout_path:
|
| 352 |
+
return candidate
|
| 353 |
+
return None
|
| 354 |
+
|
| 355 |
+
|
| 356 |
+
def _group_sessions(
|
| 357 |
+
sessions: Iterable[SessionUsage],
|
| 358 |
+
key: Callable[[SessionUsage], str],
|
| 359 |
+
*,
|
| 360 |
+
sort_by_label: bool = False,
|
| 361 |
+
) -> list[Bucket]:
|
| 362 |
+
buckets: dict[str, Bucket] = {}
|
| 363 |
+
for session in sessions:
|
| 364 |
+
label = key(session)
|
| 365 |
+
bucket = buckets.setdefault(label, Bucket(label=label))
|
| 366 |
+
bucket.add(session)
|
| 367 |
+
|
| 368 |
+
values = list(buckets.values())
|
| 369 |
+
if sort_by_label:
|
| 370 |
+
values.sort(key=lambda bucket: bucket.label)
|
| 371 |
+
else:
|
| 372 |
+
values.sort(key=lambda bucket: bucket.tokens, reverse=True)
|
| 373 |
+
return values
|
| 374 |
+
|
| 375 |
+
|
| 376 |
+
def _local_datetime(ms_value: Any, seconds_value: Any, tz: ZoneInfo) -> datetime:
|
| 377 |
+
if ms_value is not None:
|
| 378 |
+
timestamp = _int_value(ms_value) / 1000
|
| 379 |
+
else:
|
| 380 |
+
timestamp = _int_value(seconds_value)
|
| 381 |
+
return datetime.fromtimestamp(timestamp, timezone.utc).astimezone(tz)
|
| 382 |
+
|
| 383 |
+
|
| 384 |
+
def _compact_path(value: str) -> str:
|
| 385 |
+
if not value:
|
| 386 |
+
return "unknown"
|
| 387 |
+
try:
|
| 388 |
+
path = Path(value).expanduser()
|
| 389 |
+
home = Path.home()
|
| 390 |
+
if path.is_absolute():
|
| 391 |
+
relative = path.relative_to(home)
|
| 392 |
+
return "~" if str(relative) == "." else "~/" + str(relative)
|
| 393 |
+
return str(path)
|
| 394 |
+
except ValueError:
|
| 395 |
+
return value
|
| 396 |
+
|
| 397 |
+
|
| 398 |
+
def _int_value(value: Any) -> int:
|
| 399 |
+
if value is None:
|
| 400 |
+
return 0
|
| 401 |
+
try:
|
| 402 |
+
return int(value)
|
| 403 |
+
except (TypeError, ValueError):
|
| 404 |
+
return 0
|
| 405 |
+
|
| 406 |
+
|
| 407 |
+
def _string_or_none(value: Any) -> str | None:
|
| 408 |
+
if value is None:
|
| 409 |
+
return None
|
| 410 |
+
text = str(value)
|
| 411 |
+
return text if text else None
|
codex_usage_profiler/render.py
ADDED
|
@@ -0,0 +1,436 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
import html
|
| 4 |
+
from pathlib import Path
|
| 5 |
+
|
| 6 |
+
from .core import Bucket, SessionUsage, UsageReport
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
def render_markdown(report: UsageReport) -> str:
|
| 10 |
+
lines: list[str] = [
|
| 11 |
+
"# Codex Usage Report",
|
| 12 |
+
"",
|
| 13 |
+
f"Generated: {report.generated_at.isoformat(timespec='seconds')}",
|
| 14 |
+
f"Timezone: `{report.timezone_name}`",
|
| 15 |
+
f"State DB: `{report.state_path}`",
|
| 16 |
+
f"Sessions dir: `{report.sessions_dir}`",
|
| 17 |
+
f"Date range: {report.date_range_label}",
|
| 18 |
+
]
|
| 19 |
+
if report.days_filter is not None:
|
| 20 |
+
lines.append(f"Filter: last {report.days_filter} local calendar days")
|
| 21 |
+
|
| 22 |
+
lines.extend(
|
| 23 |
+
[
|
| 24 |
+
"",
|
| 25 |
+
"## Summary",
|
| 26 |
+
"",
|
| 27 |
+
_markdown_table(
|
| 28 |
+
["Metric", "Value"],
|
| 29 |
+
[
|
| 30 |
+
["Sessions", _fmt(report.sessions)],
|
| 31 |
+
["Total tokens", _fmt(report.total_tokens)],
|
| 32 |
+
["Rollouts with token breakdown", _fmt(report.parsed_rollout_count)],
|
| 33 |
+
["Missing rollouts", _fmt(report.missing_rollout_count)],
|
| 34 |
+
["Warnings", _fmt(report.warnings)],
|
| 35 |
+
],
|
| 36 |
+
),
|
| 37 |
+
"",
|
| 38 |
+
]
|
| 39 |
+
)
|
| 40 |
+
|
| 41 |
+
if report.parsed_rollout_count:
|
| 42 |
+
lines.extend(
|
| 43 |
+
[
|
| 44 |
+
"## Rollout Token Breakdown",
|
| 45 |
+
"",
|
| 46 |
+
_markdown_table(
|
| 47 |
+
["Input", "Cached input", "Output", "Reasoning output", "Rollout total"],
|
| 48 |
+
[
|
| 49 |
+
[
|
| 50 |
+
_fmt(report.rollout_totals.input_tokens),
|
| 51 |
+
_fmt(report.rollout_totals.cached_input_tokens),
|
| 52 |
+
_fmt(report.rollout_totals.output_tokens),
|
| 53 |
+
_fmt(report.rollout_totals.reasoning_output_tokens),
|
| 54 |
+
_fmt(report.rollout_totals.total_tokens),
|
| 55 |
+
]
|
| 56 |
+
],
|
| 57 |
+
),
|
| 58 |
+
"",
|
| 59 |
+
]
|
| 60 |
+
)
|
| 61 |
+
|
| 62 |
+
sections: list[tuple[str, list[Bucket]]] = [
|
| 63 |
+
("Daily Tokens", report.daily),
|
| 64 |
+
("Weekly Tokens", report.weekly),
|
| 65 |
+
("Tokens By Cwd", report.by_cwd),
|
| 66 |
+
("Tokens By Model", report.by_model),
|
| 67 |
+
("Tokens By Role", report.by_role),
|
| 68 |
+
("Main Vs Subagent", report.by_kind),
|
| 69 |
+
]
|
| 70 |
+
for title, buckets in sections:
|
| 71 |
+
lines.extend(["## " + title, "", _render_bucket_markdown(buckets), ""])
|
| 72 |
+
|
| 73 |
+
lines.extend(["## Top Sessions", "", _render_top_sessions_markdown(report.top_sessions), ""])
|
| 74 |
+
|
| 75 |
+
if report.warnings:
|
| 76 |
+
lines.extend(
|
| 77 |
+
[
|
| 78 |
+
"## Data Warnings",
|
| 79 |
+
"",
|
| 80 |
+
*[f"- `{_escape_md(warning)}`" for warning in report.warnings[:50]],
|
| 81 |
+
]
|
| 82 |
+
)
|
| 83 |
+
if len(report.warnings) > 50:
|
| 84 |
+
lines.append(f"- ... {len(report.warnings) - 50} more")
|
| 85 |
+
lines.append("")
|
| 86 |
+
|
| 87 |
+
return "\n".join(lines).rstrip() + "\n"
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
def render_html(report: UsageReport) -> str:
|
| 91 |
+
sections = "\n".join(
|
| 92 |
+
[
|
| 93 |
+
_html_section("Daily Tokens", _render_bucket_html(report.daily)),
|
| 94 |
+
_html_section("Weekly Tokens", _render_bucket_html(report.weekly)),
|
| 95 |
+
_html_section("Tokens By Cwd", _render_bucket_html(report.by_cwd)),
|
| 96 |
+
_html_section("Tokens By Model", _render_bucket_html(report.by_model)),
|
| 97 |
+
_html_section("Tokens By Role", _render_bucket_html(report.by_role)),
|
| 98 |
+
_html_section("Main Vs Subagent", _render_bucket_html(report.by_kind)),
|
| 99 |
+
_html_section("Top Sessions", _render_top_sessions_html(report.top_sessions)),
|
| 100 |
+
]
|
| 101 |
+
)
|
| 102 |
+
|
| 103 |
+
rollout_section = ""
|
| 104 |
+
if report.parsed_rollout_count:
|
| 105 |
+
rollout_section = _html_section(
|
| 106 |
+
"Rollout Token Breakdown",
|
| 107 |
+
_html_table(
|
| 108 |
+
["Input", "Cached input", "Output", "Reasoning output", "Rollout total"],
|
| 109 |
+
[
|
| 110 |
+
[
|
| 111 |
+
_fmt(report.rollout_totals.input_tokens),
|
| 112 |
+
_fmt(report.rollout_totals.cached_input_tokens),
|
| 113 |
+
_fmt(report.rollout_totals.output_tokens),
|
| 114 |
+
_fmt(report.rollout_totals.reasoning_output_tokens),
|
| 115 |
+
_fmt(report.rollout_totals.total_tokens),
|
| 116 |
+
]
|
| 117 |
+
],
|
| 118 |
+
),
|
| 119 |
+
)
|
| 120 |
+
|
| 121 |
+
warnings_section = ""
|
| 122 |
+
if report.warnings:
|
| 123 |
+
items = "\n".join(
|
| 124 |
+
f"<li><code>{html.escape(warning)}</code></li>" for warning in report.warnings[:50]
|
| 125 |
+
)
|
| 126 |
+
if len(report.warnings) > 50:
|
| 127 |
+
items += f"\n<li>{len(report.warnings) - 50} more</li>"
|
| 128 |
+
warnings_section = _html_section("Data Warnings", f"<ul>{items}</ul>")
|
| 129 |
+
|
| 130 |
+
filter_line = ""
|
| 131 |
+
if report.days_filter is not None:
|
| 132 |
+
filter_line = f"<p>Filter: last {report.days_filter} local calendar days</p>"
|
| 133 |
+
|
| 134 |
+
return f"""<!doctype html>
|
| 135 |
+
<html lang="en">
|
| 136 |
+
<head>
|
| 137 |
+
<meta charset="utf-8">
|
| 138 |
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
| 139 |
+
<title>Codex Usage Report</title>
|
| 140 |
+
<style>
|
| 141 |
+
:root {{
|
| 142 |
+
color-scheme: light dark;
|
| 143 |
+
--bg: #f7f7f4;
|
| 144 |
+
--panel: #ffffff;
|
| 145 |
+
--text: #1f2528;
|
| 146 |
+
--muted: #667078;
|
| 147 |
+
--border: #d9ddd8;
|
| 148 |
+
--accent: #176b5d;
|
| 149 |
+
--row: #f1f4f2;
|
| 150 |
+
}}
|
| 151 |
+
@media (prefers-color-scheme: dark) {{
|
| 152 |
+
:root {{
|
| 153 |
+
--bg: #151716;
|
| 154 |
+
--panel: #1d211f;
|
| 155 |
+
--text: #eef1ee;
|
| 156 |
+
--muted: #a6aea9;
|
| 157 |
+
--border: #373d39;
|
| 158 |
+
--accent: #74c7b8;
|
| 159 |
+
--row: #242a27;
|
| 160 |
+
}}
|
| 161 |
+
}}
|
| 162 |
+
body {{
|
| 163 |
+
margin: 0;
|
| 164 |
+
background: var(--bg);
|
| 165 |
+
color: var(--text);
|
| 166 |
+
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
| 167 |
+
line-height: 1.45;
|
| 168 |
+
}}
|
| 169 |
+
main {{
|
| 170 |
+
max-width: 1180px;
|
| 171 |
+
margin: 0 auto;
|
| 172 |
+
padding: 32px 20px 56px;
|
| 173 |
+
}}
|
| 174 |
+
h1 {{
|
| 175 |
+
margin: 0 0 10px;
|
| 176 |
+
font-size: 2rem;
|
| 177 |
+
letter-spacing: 0;
|
| 178 |
+
}}
|
| 179 |
+
h2 {{
|
| 180 |
+
margin: 32px 0 12px;
|
| 181 |
+
font-size: 1.1rem;
|
| 182 |
+
letter-spacing: 0;
|
| 183 |
+
}}
|
| 184 |
+
.meta {{
|
| 185 |
+
color: var(--muted);
|
| 186 |
+
display: grid;
|
| 187 |
+
gap: 4px;
|
| 188 |
+
margin-bottom: 24px;
|
| 189 |
+
}}
|
| 190 |
+
.summary {{
|
| 191 |
+
display: grid;
|
| 192 |
+
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
| 193 |
+
gap: 12px;
|
| 194 |
+
}}
|
| 195 |
+
.metric {{
|
| 196 |
+
background: var(--panel);
|
| 197 |
+
border: 1px solid var(--border);
|
| 198 |
+
border-radius: 8px;
|
| 199 |
+
padding: 14px 16px;
|
| 200 |
+
}}
|
| 201 |
+
.metric span {{
|
| 202 |
+
display: block;
|
| 203 |
+
color: var(--muted);
|
| 204 |
+
font-size: .85rem;
|
| 205 |
+
}}
|
| 206 |
+
.metric strong {{
|
| 207 |
+
display: block;
|
| 208 |
+
margin-top: 4px;
|
| 209 |
+
font-size: 1.25rem;
|
| 210 |
+
}}
|
| 211 |
+
.table-wrap {{
|
| 212 |
+
overflow-x: auto;
|
| 213 |
+
border: 1px solid var(--border);
|
| 214 |
+
background: var(--panel);
|
| 215 |
+
border-radius: 8px;
|
| 216 |
+
}}
|
| 217 |
+
table {{
|
| 218 |
+
border-collapse: collapse;
|
| 219 |
+
width: 100%;
|
| 220 |
+
min-width: 640px;
|
| 221 |
+
}}
|
| 222 |
+
th, td {{
|
| 223 |
+
padding: 9px 11px;
|
| 224 |
+
border-bottom: 1px solid var(--border);
|
| 225 |
+
text-align: left;
|
| 226 |
+
vertical-align: top;
|
| 227 |
+
white-space: nowrap;
|
| 228 |
+
}}
|
| 229 |
+
th {{
|
| 230 |
+
color: var(--muted);
|
| 231 |
+
font-weight: 650;
|
| 232 |
+
font-size: .82rem;
|
| 233 |
+
background: var(--row);
|
| 234 |
+
}}
|
| 235 |
+
tr:last-child td {{
|
| 236 |
+
border-bottom: 0;
|
| 237 |
+
}}
|
| 238 |
+
td.num {{
|
| 239 |
+
text-align: right;
|
| 240 |
+
font-variant-numeric: tabular-nums;
|
| 241 |
+
}}
|
| 242 |
+
code {{
|
| 243 |
+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
| 244 |
+
font-size: .9em;
|
| 245 |
+
}}
|
| 246 |
+
.empty {{
|
| 247 |
+
color: var(--muted);
|
| 248 |
+
margin: 0;
|
| 249 |
+
}}
|
| 250 |
+
</style>
|
| 251 |
+
</head>
|
| 252 |
+
<body>
|
| 253 |
+
<main>
|
| 254 |
+
<h1>Codex Usage Report</h1>
|
| 255 |
+
<div class="meta">
|
| 256 |
+
<div>Generated: {html.escape(report.generated_at.isoformat(timespec="seconds"))}</div>
|
| 257 |
+
<div>Timezone: <code>{html.escape(report.timezone_name)}</code></div>
|
| 258 |
+
<div>State DB: <code>{html.escape(str(report.state_path))}</code></div>
|
| 259 |
+
<div>Sessions dir: <code>{html.escape(str(report.sessions_dir))}</code></div>
|
| 260 |
+
<div>Date range: {html.escape(report.date_range_label)}</div>
|
| 261 |
+
{filter_line}
|
| 262 |
+
</div>
|
| 263 |
+
<section class="summary">
|
| 264 |
+
{_metric("Sessions", _fmt(report.sessions))}
|
| 265 |
+
{_metric("Total tokens", _fmt(report.total_tokens))}
|
| 266 |
+
{_metric("Rollout breakdowns", _fmt(report.parsed_rollout_count))}
|
| 267 |
+
{_metric("Missing rollouts", _fmt(report.missing_rollout_count))}
|
| 268 |
+
{_metric("Warnings", _fmt(report.warnings))}
|
| 269 |
+
</section>
|
| 270 |
+
{rollout_section}
|
| 271 |
+
{sections}
|
| 272 |
+
{warnings_section}
|
| 273 |
+
</main>
|
| 274 |
+
</body>
|
| 275 |
+
</html>
|
| 276 |
+
"""
|
| 277 |
+
|
| 278 |
+
|
| 279 |
+
def write_reports(report: UsageReport, out_dir: Path, output_format: str) -> list[Path]:
|
| 280 |
+
out_dir.mkdir(parents=True, exist_ok=True)
|
| 281 |
+
written: list[Path] = []
|
| 282 |
+
if output_format in {"md", "both"}:
|
| 283 |
+
path = out_dir / "codex-usage.md"
|
| 284 |
+
path.write_text(render_markdown(report), encoding="utf-8")
|
| 285 |
+
written.append(path)
|
| 286 |
+
if output_format in {"html", "both"}:
|
| 287 |
+
path = out_dir / "codex-usage.html"
|
| 288 |
+
path.write_text(render_html(report), encoding="utf-8")
|
| 289 |
+
written.append(path)
|
| 290 |
+
return written
|
| 291 |
+
|
| 292 |
+
|
| 293 |
+
def _render_bucket_markdown(buckets: list[Bucket]) -> str:
|
| 294 |
+
return _markdown_table(
|
| 295 |
+
["Label", "Sessions", "Tokens", "Rollout total", "Input", "Cached input", "Output", "Reasoning"],
|
| 296 |
+
[
|
| 297 |
+
[
|
| 298 |
+
bucket.label,
|
| 299 |
+
_fmt(bucket.sessions),
|
| 300 |
+
_fmt(bucket.tokens),
|
| 301 |
+
_fmt(bucket.rollout.total_tokens),
|
| 302 |
+
_fmt(bucket.rollout.input_tokens),
|
| 303 |
+
_fmt(bucket.rollout.cached_input_tokens),
|
| 304 |
+
_fmt(bucket.rollout.output_tokens),
|
| 305 |
+
_fmt(bucket.rollout.reasoning_output_tokens),
|
| 306 |
+
]
|
| 307 |
+
for bucket in buckets
|
| 308 |
+
],
|
| 309 |
+
)
|
| 310 |
+
|
| 311 |
+
|
| 312 |
+
def _render_bucket_html(buckets: list[Bucket]) -> str:
|
| 313 |
+
return _html_table(
|
| 314 |
+
["Label", "Sessions", "Tokens", "Rollout total", "Input", "Cached input", "Output", "Reasoning"],
|
| 315 |
+
[
|
| 316 |
+
[
|
| 317 |
+
bucket.label,
|
| 318 |
+
_fmt(bucket.sessions),
|
| 319 |
+
_fmt(bucket.tokens),
|
| 320 |
+
_fmt(bucket.rollout.total_tokens),
|
| 321 |
+
_fmt(bucket.rollout.input_tokens),
|
| 322 |
+
_fmt(bucket.rollout.cached_input_tokens),
|
| 323 |
+
_fmt(bucket.rollout.output_tokens),
|
| 324 |
+
_fmt(bucket.rollout.reasoning_output_tokens),
|
| 325 |
+
]
|
| 326 |
+
for bucket in buckets
|
| 327 |
+
],
|
| 328 |
+
numeric_columns={1, 2, 3, 4, 5, 6, 7},
|
| 329 |
+
)
|
| 330 |
+
|
| 331 |
+
|
| 332 |
+
def _render_top_sessions_markdown(sessions: list[SessionUsage]) -> str:
|
| 333 |
+
return _markdown_table(
|
| 334 |
+
["Created", "Tokens", "Kind", "Model", "Role", "Cwd", "Session", "Rollout"],
|
| 335 |
+
[
|
| 336 |
+
[
|
| 337 |
+
session.created_at.strftime("%Y-%m-%d %H:%M"),
|
| 338 |
+
_fmt(session.tokens),
|
| 339 |
+
session.kind,
|
| 340 |
+
session.model,
|
| 341 |
+
session.role,
|
| 342 |
+
_compact_for_report(session.cwd),
|
| 343 |
+
session.thread_id,
|
| 344 |
+
str(session.rollout_path or ""),
|
| 345 |
+
]
|
| 346 |
+
for session in sessions
|
| 347 |
+
],
|
| 348 |
+
)
|
| 349 |
+
|
| 350 |
+
|
| 351 |
+
def _render_top_sessions_html(sessions: list[SessionUsage]) -> str:
|
| 352 |
+
return _html_table(
|
| 353 |
+
["Created", "Tokens", "Kind", "Model", "Role", "Cwd", "Session", "Rollout"],
|
| 354 |
+
[
|
| 355 |
+
[
|
| 356 |
+
session.created_at.strftime("%Y-%m-%d %H:%M"),
|
| 357 |
+
_fmt(session.tokens),
|
| 358 |
+
session.kind,
|
| 359 |
+
session.model,
|
| 360 |
+
session.role,
|
| 361 |
+
_compact_for_report(session.cwd),
|
| 362 |
+
session.thread_id,
|
| 363 |
+
str(session.rollout_path or ""),
|
| 364 |
+
]
|
| 365 |
+
for session in sessions
|
| 366 |
+
],
|
| 367 |
+
numeric_columns={1},
|
| 368 |
+
)
|
| 369 |
+
|
| 370 |
+
|
| 371 |
+
def _markdown_table(headers: list[str], rows: list[list[str]]) -> str:
|
| 372 |
+
if not rows:
|
| 373 |
+
return "_No rows._"
|
| 374 |
+
escaped_headers = [_escape_md(header) for header in headers]
|
| 375 |
+
lines = [
|
| 376 |
+
"| " + " | ".join(escaped_headers) + " |",
|
| 377 |
+
"| " + " | ".join("---" for _ in headers) + " |",
|
| 378 |
+
]
|
| 379 |
+
for row in rows:
|
| 380 |
+
lines.append("| " + " | ".join(_escape_md(str(cell)) for cell in row) + " |")
|
| 381 |
+
return "\n".join(lines)
|
| 382 |
+
|
| 383 |
+
|
| 384 |
+
def _html_table(
|
| 385 |
+
headers: list[str], rows: list[list[str]], *, numeric_columns: set[int] | None = None
|
| 386 |
+
) -> str:
|
| 387 |
+
if not rows:
|
| 388 |
+
return '<p class="empty">No rows.</p>'
|
| 389 |
+
numeric_columns = numeric_columns or set()
|
| 390 |
+
head = "".join(f"<th>{html.escape(header)}</th>" for header in headers)
|
| 391 |
+
body_rows = []
|
| 392 |
+
for row in rows:
|
| 393 |
+
cells = []
|
| 394 |
+
for index, cell in enumerate(row):
|
| 395 |
+
klass = ' class="num"' if index in numeric_columns else ""
|
| 396 |
+
cells.append(f"<td{klass}>{html.escape(str(cell))}</td>")
|
| 397 |
+
body_rows.append("<tr>" + "".join(cells) + "</tr>")
|
| 398 |
+
return (
|
| 399 |
+
'<div class="table-wrap"><table><thead><tr>'
|
| 400 |
+
+ head
|
| 401 |
+
+ "</tr></thead><tbody>"
|
| 402 |
+
+ "".join(body_rows)
|
| 403 |
+
+ "</tbody></table></div>"
|
| 404 |
+
)
|
| 405 |
+
|
| 406 |
+
|
| 407 |
+
def _html_section(title: str, content: str) -> str:
|
| 408 |
+
return f"<section><h2>{html.escape(title)}</h2>{content}</section>"
|
| 409 |
+
|
| 410 |
+
|
| 411 |
+
def _metric(label: str, value: str) -> str:
|
| 412 |
+
return f'<div class="metric"><span>{html.escape(label)}</span><strong>{html.escape(value)}</strong></div>'
|
| 413 |
+
|
| 414 |
+
|
| 415 |
+
def _fmt(value: int | list[object]) -> str:
|
| 416 |
+
if isinstance(value, list):
|
| 417 |
+
value = len(value)
|
| 418 |
+
return f"{value:,}"
|
| 419 |
+
|
| 420 |
+
|
| 421 |
+
def _escape_md(value: str) -> str:
|
| 422 |
+
return value.replace("\\", "\\\\").replace("|", "\\|").replace("\n", " ")
|
| 423 |
+
|
| 424 |
+
|
| 425 |
+
def _compact_for_report(value: str) -> str:
|
| 426 |
+
if not value:
|
| 427 |
+
return "unknown"
|
| 428 |
+
try:
|
| 429 |
+
path = Path(value).expanduser()
|
| 430 |
+
home = Path.home()
|
| 431 |
+
if path.is_absolute():
|
| 432 |
+
relative = path.relative_to(home)
|
| 433 |
+
return "~" if str(relative) == "." else "~/" + str(relative)
|
| 434 |
+
return str(path)
|
| 435 |
+
except ValueError:
|
| 436 |
+
return value
|
pyproject.toml
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[build-system]
|
| 2 |
+
requires = ["setuptools>=68"]
|
| 3 |
+
build-backend = "setuptools.build_meta"
|
| 4 |
+
|
| 5 |
+
[project]
|
| 6 |
+
name = "codex-usage-profiler"
|
| 7 |
+
version = "0.1.0"
|
| 8 |
+
description = "Local profiler for Codex state_5.sqlite and rollout JSONL usage data"
|
| 9 |
+
readme = "README.md"
|
| 10 |
+
requires-python = ">=3.11"
|
| 11 |
+
dependencies = []
|
| 12 |
+
|
| 13 |
+
[project.scripts]
|
| 14 |
+
codex-usage-profiler = "codex_usage_profiler.cli:main"
|
| 15 |
+
|
| 16 |
+
[tool.setuptools.packages.find]
|
| 17 |
+
include = ["codex_usage_profiler*"]
|
reports-last7/codex-usage.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Codex Usage Report
|
| 2 |
+
|
| 3 |
+
Generated: 2026-04-22T00:49:13+02:00
|
| 4 |
+
Timezone: `Europe/Berlin`
|
| 5 |
+
State DB: `/home/smlflg/.codex/state_5.sqlite`
|
| 6 |
+
Sessions dir: `/home/smlflg/.codex/sessions`
|
| 7 |
+
Date range: 2026-04-16 to 2026-04-22
|
| 8 |
+
Filter: last 7 local calendar days
|
| 9 |
+
|
| 10 |
+
## Summary
|
| 11 |
+
|
| 12 |
+
| Metric | Value |
|
| 13 |
+
| --- | --- |
|
| 14 |
+
| Sessions | 134 |
|
| 15 |
+
| Total tokens | 396,472,202 |
|
| 16 |
+
| Rollouts with token breakdown | 132 |
|
| 17 |
+
| Missing rollouts | 0 |
|
| 18 |
+
| Warnings | 1 |
|
| 19 |
+
|
| 20 |
+
## Rollout Token Breakdown
|
| 21 |
+
|
| 22 |
+
| Input | Cached input | Output | Reasoning output | Rollout total |
|
| 23 |
+
| --- | --- | --- | --- | --- |
|
| 24 |
+
| 394,419,162 | 366,772,096 | 2,309,042 | 820,743 | 396,728,204 |
|
| 25 |
+
|
| 26 |
+
## Daily Tokens
|
| 27 |
+
|
| 28 |
+
| Label | Sessions | Tokens | Rollout total | Input | Cached input | Output | Reasoning |
|
| 29 |
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
| 30 |
+
| 2026-04-16 | 3 | 59,357,456 | 59,357,456 | 59,092,558 | 56,559,360 | 264,898 | 125,030 |
|
| 31 |
+
| 2026-04-20 | 1 | 13,711,641 | 13,711,641 | 13,653,855 | 13,032,832 | 57,786 | 12,196 |
|
| 32 |
+
| 2026-04-21 | 115 | 300,116,344 | 300,116,344 | 298,325,385 | 276,096,768 | 1,790,959 | 610,982 |
|
| 33 |
+
| 2026-04-22 | 15 | 23,286,761 | 23,542,763 | 23,347,364 | 21,083,136 | 195,399 | 72,535 |
|
| 34 |
+
|
| 35 |
+
## Weekly Tokens
|
| 36 |
+
|
| 37 |
+
| Label | Sessions | Tokens | Rollout total | Input | Cached input | Output | Reasoning |
|
| 38 |
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
| 39 |
+
| 2026-W16 | 3 | 59,357,456 | 59,357,456 | 59,092,558 | 56,559,360 | 264,898 | 125,030 |
|
| 40 |
+
| 2026-W17 | 131 | 337,114,746 | 337,370,748 | 335,326,604 | 310,212,736 | 2,044,144 | 695,713 |
|
| 41 |
+
|
| 42 |
+
## Tokens By Cwd
|
| 43 |
+
|
| 44 |
+
| Label | Sessions | Tokens | Rollout total | Input | Cached input | Output | Reasoning |
|
| 45 |
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
| 46 |
+
| ~/Projekte/PromptBoost | 40 | 91,369,695 | 91,369,695 | 90,715,571 | 84,423,552 | 654,124 | 254,702 |
|
| 47 |
+
| ~/Projekte/HeumandenParty | 23 | 81,899,777 | 81,899,777 | 81,449,087 | 76,069,888 | 450,690 | 171,495 |
|
| 48 |
+
| ~/Projekte/FirstRealHarnessEvaluation_KarpathiesMD | 2 | 59,357,456 | 59,357,456 | 59,092,558 | 56,559,360 | 264,898 | 125,030 |
|
| 49 |
+
| ~ | 23 | 48,541,135 | 48,541,135 | 48,305,111 | 44,374,144 | 236,024 | 68,175 |
|
| 50 |
+
| ~/Projekte | 18 | 37,257,578 | 37,257,578 | 37,030,877 | 33,269,376 | 226,701 | 61,080 |
|
| 51 |
+
| ~/Projekte/PromptBoost/personalPromptBoost | 13 | 22,802,481 | 22,802,481 | 22,611,147 | 20,876,160 | 191,334 | 57,401 |
|
| 52 |
+
| ~/Projekte/PromptGarage | 1 | 19,452,133 | 19,452,133 | 19,394,544 | 18,764,544 | 57,589 | 18,018 |
|
| 53 |
+
| ~/Projekte/PseudoLogikPyhthonCPP | 2 | 16,329,762 | 16,329,762 | 16,254,080 | 15,190,656 | 75,682 | 20,994 |
|
| 54 |
+
| ~/Codex | 3 | 7,952,365 | 8,166,946 | 8,114,601 | 7,161,344 | 52,345 | 14,392 |
|
| 55 |
+
| ~/Projekte/BahnAgent | 2 | 4,575,173 | 4,575,173 | 4,549,935 | 3,969,920 | 25,238 | 3,688 |
|
| 56 |
+
| ~/.claude | 1 | 2,724,909 | 2,724,909 | 2,707,930 | 2,457,344 | 16,979 | 4,749 |
|
| 57 |
+
| ~/Projekte/Codex_Usage_Profil | 1 | 2,167,223 | 2,167,223 | 2,142,329 | 1,986,304 | 24,894 | 6,969 |
|
| 58 |
+
| ~/Projekte/ACPcodex | 1 | 1,059,170 | 1,059,170 | 1,043,792 | 910,848 | 15,378 | 8,018 |
|
| 59 |
+
| ~/Projekte/Kaggle5dayAgent | 2 | 913,047 | 913,047 | 897,573 | 686,592 | 15,474 | 5,673 |
|
| 60 |
+
| ~/Projekte/HarnessEcosystem/sidebyside | 2 | 70,298 | 111,719 | 110,027 | 72,064 | 1,692 | 359 |
|
| 61 |
+
|
| 62 |
+
## Tokens By Model
|
| 63 |
+
|
| 64 |
+
| Label | Sessions | Tokens | Rollout total | Input | Cached input | Output | Reasoning |
|
| 65 |
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
| 66 |
+
| gpt-5.4 | 81 | 327,418,371 | 327,658,970 | 325,872,479 | 302,350,848 | 1,786,491 | 532,886 |
|
| 67 |
+
| gpt-5.4-mini | 52 | 69,053,831 | 69,069,234 | 68,546,683 | 64,421,248 | 522,551 | 287,857 |
|
| 68 |
+
| unknown | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
|
| 69 |
+
|
| 70 |
+
## Tokens By Role
|
| 71 |
+
|
| 72 |
+
| Label | Sessions | Tokens | Rollout total | Input | Cached input | Output | Reasoning |
|
| 73 |
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
| 74 |
+
| main | 34 | 344,072,714 | 344,313,313 | 342,760,455 | 322,165,888 | 1,552,858 | 493,488 |
|
| 75 |
+
| unknown | 17 | 31,239,166 | 31,239,166 | 30,924,883 | 27,394,176 | 314,283 | 116,098 |
|
| 76 |
+
| explorer | 72 | 15,482,699 | 15,498,102 | 15,170,418 | 12,131,712 | 327,684 | 163,970 |
|
| 77 |
+
| worker | 5 | 5,588,454 | 5,588,454 | 5,474,360 | 5,029,376 | 114,094 | 47,118 |
|
| 78 |
+
| default | 6 | 89,169 | 89,169 | 89,046 | 50,944 | 123 | 69 |
|
| 79 |
+
|
| 80 |
+
## Main Vs Subagent
|
| 81 |
+
|
| 82 |
+
| Label | Sessions | Tokens | Rollout total | Input | Cached input | Output | Reasoning |
|
| 83 |
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
| 84 |
+
| main | 34 | 344,072,714 | 344,313,313 | 342,760,455 | 322,165,888 | 1,552,858 | 493,488 |
|
| 85 |
+
| subagent | 100 | 52,399,488 | 52,414,891 | 51,658,707 | 44,606,208 | 756,184 | 327,255 |
|
| 86 |
+
|
| 87 |
+
## Top Sessions
|
| 88 |
+
|
| 89 |
+
| Created | Tokens | Kind | Model | Role | Cwd | Session | Rollout |
|
| 90 |
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
| 91 |
+
| 2026-04-16 13:01 | 47,959,797 | main | gpt-5.4-mini | main | ~/Projekte/FirstRealHarnessEvaluation_KarpathiesMD | 019d95f4-0198-7e10-9c95-ecd79e771e27 | /home/smlflg/.codex/sessions/2026/04/16/rollout-2026-04-16T13-01-29-019d95f4-0198-7e10-9c95-ecd79e771e27.jsonl |
|
| 92 |
+
| 2026-04-21 23:03 | 32,619,865 | main | gpt-5.4 | main | ~/Projekte/HeumandenParty | 019db1db-150f-7662-b607-30871c33af75 | /home/smlflg/.codex/sessions/2026/04/21/rollout-2026-04-21T23-03-38-019db1db-150f-7662-b607-30871c33af75.jsonl |
|
| 93 |
+
| 2026-04-21 23:28 | 21,430,259 | main | gpt-5.4 | main | ~/Projekte/HeumandenParty | 019db1f1-e994-75c0-94d8-6edc93203dd7 | /home/smlflg/.codex/sessions/2026/04/21/rollout-2026-04-21T23-28-34-019db1f1-e994-75c0-94d8-6edc93203dd7.jsonl |
|
| 94 |
+
| 2026-04-21 15:43 | 21,410,253 | main | gpt-5.4 | main | ~ | 019db048-0123-7242-89b9-d6083591212b | /home/smlflg/.codex/sessions/2026/04/21/rollout-2026-04-21T15-43-22-019db048-0123-7242-89b9-d6083591212b.jsonl |
|
| 95 |
+
| 2026-04-21 15:31 | 21,194,654 | main | gpt-5.4 | main | ~/Projekte/PromptBoost | 019db03d-1f96-7592-8fef-1f10125ebe0c | /home/smlflg/.codex/sessions/2026/04/21/rollout-2026-04-21T15-31-29-019db03d-1f96-7592-8fef-1f10125ebe0c.jsonl |
|
| 96 |
+
|
| 97 |
+
## Data Warnings
|
| 98 |
+
|
| 99 |
+
- `Malformed JSONL lines in /home/smlflg/.codex/sessions/2026/04/21/rollout-2026-04-21T18-15-04-019db0d2-e62b-78b3-b8f3-e0c70af3aa6c.jsonl: 1`
|
reports/codex-usage.html
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!doctype html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="utf-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
| 6 |
+
<title>Codex Usage Report</title>
|
| 7 |
+
<style>
|
| 8 |
+
:root {
|
| 9 |
+
color-scheme: light dark;
|
| 10 |
+
--bg: #f7f7f4;
|
| 11 |
+
--panel: #ffffff;
|
| 12 |
+
--text: #1f2528;
|
| 13 |
+
--muted: #667078;
|
| 14 |
+
--border: #d9ddd8;
|
| 15 |
+
--accent: #176b5d;
|
| 16 |
+
--row: #f1f4f2;
|
| 17 |
+
}
|
| 18 |
+
@media (prefers-color-scheme: dark) {
|
| 19 |
+
:root {
|
| 20 |
+
--bg: #151716;
|
| 21 |
+
--panel: #1d211f;
|
| 22 |
+
--text: #eef1ee;
|
| 23 |
+
--muted: #a6aea9;
|
| 24 |
+
--border: #373d39;
|
| 25 |
+
--accent: #74c7b8;
|
| 26 |
+
--row: #242a27;
|
| 27 |
+
}
|
| 28 |
+
}
|
| 29 |
+
body {
|
| 30 |
+
margin: 0;
|
| 31 |
+
background: var(--bg);
|
| 32 |
+
color: var(--text);
|
| 33 |
+
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
| 34 |
+
line-height: 1.45;
|
| 35 |
+
}
|
| 36 |
+
main {
|
| 37 |
+
max-width: 1180px;
|
| 38 |
+
margin: 0 auto;
|
| 39 |
+
padding: 32px 20px 56px;
|
| 40 |
+
}
|
| 41 |
+
h1 {
|
| 42 |
+
margin: 0 0 10px;
|
| 43 |
+
font-size: 2rem;
|
| 44 |
+
letter-spacing: 0;
|
| 45 |
+
}
|
| 46 |
+
h2 {
|
| 47 |
+
margin: 32px 0 12px;
|
| 48 |
+
font-size: 1.1rem;
|
| 49 |
+
letter-spacing: 0;
|
| 50 |
+
}
|
| 51 |
+
.meta {
|
| 52 |
+
color: var(--muted);
|
| 53 |
+
display: grid;
|
| 54 |
+
gap: 4px;
|
| 55 |
+
margin-bottom: 24px;
|
| 56 |
+
}
|
| 57 |
+
.summary {
|
| 58 |
+
display: grid;
|
| 59 |
+
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
| 60 |
+
gap: 12px;
|
| 61 |
+
}
|
| 62 |
+
.metric {
|
| 63 |
+
background: var(--panel);
|
| 64 |
+
border: 1px solid var(--border);
|
| 65 |
+
border-radius: 8px;
|
| 66 |
+
padding: 14px 16px;
|
| 67 |
+
}
|
| 68 |
+
.metric span {
|
| 69 |
+
display: block;
|
| 70 |
+
color: var(--muted);
|
| 71 |
+
font-size: .85rem;
|
| 72 |
+
}
|
| 73 |
+
.metric strong {
|
| 74 |
+
display: block;
|
| 75 |
+
margin-top: 4px;
|
| 76 |
+
font-size: 1.25rem;
|
| 77 |
+
}
|
| 78 |
+
.table-wrap {
|
| 79 |
+
overflow-x: auto;
|
| 80 |
+
border: 1px solid var(--border);
|
| 81 |
+
background: var(--panel);
|
| 82 |
+
border-radius: 8px;
|
| 83 |
+
}
|
| 84 |
+
table {
|
| 85 |
+
border-collapse: collapse;
|
| 86 |
+
width: 100%;
|
| 87 |
+
min-width: 640px;
|
| 88 |
+
}
|
| 89 |
+
th, td {
|
| 90 |
+
padding: 9px 11px;
|
| 91 |
+
border-bottom: 1px solid var(--border);
|
| 92 |
+
text-align: left;
|
| 93 |
+
vertical-align: top;
|
| 94 |
+
white-space: nowrap;
|
| 95 |
+
}
|
| 96 |
+
th {
|
| 97 |
+
color: var(--muted);
|
| 98 |
+
font-weight: 650;
|
| 99 |
+
font-size: .82rem;
|
| 100 |
+
background: var(--row);
|
| 101 |
+
}
|
| 102 |
+
tr:last-child td {
|
| 103 |
+
border-bottom: 0;
|
| 104 |
+
}
|
| 105 |
+
td.num {
|
| 106 |
+
text-align: right;
|
| 107 |
+
font-variant-numeric: tabular-nums;
|
| 108 |
+
}
|
| 109 |
+
code {
|
| 110 |
+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
| 111 |
+
font-size: .9em;
|
| 112 |
+
}
|
| 113 |
+
.empty {
|
| 114 |
+
color: var(--muted);
|
| 115 |
+
margin: 0;
|
| 116 |
+
}
|
| 117 |
+
</style>
|
| 118 |
+
</head>
|
| 119 |
+
<body>
|
| 120 |
+
<main>
|
| 121 |
+
<h1>Codex Usage Report</h1>
|
| 122 |
+
<div class="meta">
|
| 123 |
+
<div>Generated: 2026-04-22T00:48:49+02:00</div>
|
| 124 |
+
<div>Timezone: <code>Europe/Berlin</code></div>
|
| 125 |
+
<div>State DB: <code>/home/smlflg/.codex/state_5.sqlite</code></div>
|
| 126 |
+
<div>Sessions dir: <code>/home/smlflg/.codex/sessions</code></div>
|
| 127 |
+
<div>Date range: 2026-02-03 to 2026-04-22</div>
|
| 128 |
+
|
| 129 |
+
</div>
|
| 130 |
+
<section class="summary">
|
| 131 |
+
<div class="metric"><span>Sessions</span><strong>375</strong></div>
|
| 132 |
+
<div class="metric"><span>Total tokens</span><strong>1,255,210,700</strong></div>
|
| 133 |
+
<div class="metric"><span>Rollout breakdowns</span><strong>359</strong></div>
|
| 134 |
+
<div class="metric"><span>Missing rollouts</span><strong>0</strong></div>
|
| 135 |
+
<div class="metric"><span>Warnings</span><strong>1</strong></div>
|
| 136 |
+
</section>
|
| 137 |
+
<section><h2>Rollout Token Breakdown</h2><div class="table-wrap"><table><thead><tr><th>Input</th><th>Cached input</th><th>Output</th><th>Reasoning output</th><th>Rollout total</th></tr></thead><tbody><tr><td>1,247,663,109</td><td>1,120,145,792</td><td>7,547,591</td><td>2,657,540</td><td>1,255,210,700</td></tr></tbody></table></div></section>
|
| 138 |
+
<section><h2>Daily Tokens</h2><div class="table-wrap"><table><thead><tr><th>Label</th><th>Sessions</th><th>Tokens</th><th>Rollout total</th><th>Input</th><th>Cached input</th><th>Output</th><th>Reasoning</th></tr></thead><tbody><tr><td>2026-02-03</td><td class="num">4</td><td class="num">2,592,334</td><td class="num">2,592,334</td><td class="num">2,568,243</td><td class="num">2,210,560</td><td class="num">24,091</td><td class="num">11,520</td></tr><tr><td>2026-02-04</td><td class="num">1</td><td class="num">1,714,675</td><td class="num">1,714,675</td><td class="num">1,654,679</td><td class="num">1,327,104</td><td class="num">59,996</td><td class="num">47,296</td></tr><tr><td>2026-02-05</td><td class="num">3</td><td class="num">41,998,810</td><td class="num">41,998,810</td><td class="num">41,824,072</td><td class="num">36,333,696</td><td class="num">174,738</td><td class="num">62,720</td></tr><tr><td>2026-02-06</td><td class="num">2</td><td class="num">3,102,257</td><td class="num">3,102,257</td><td class="num">3,087,487</td><td class="num">2,501,760</td><td class="num">14,770</td><td class="num">5,248</td></tr><tr><td>2026-02-07</td><td class="num">3</td><td class="num">28,416,733</td><td class="num">28,416,733</td><td class="num">28,275,656</td><td class="num">24,109,568</td><td class="num">141,077</td><td class="num">51,584</td></tr><tr><td>2026-02-08</td><td class="num">1</td><td class="num">1,722,562</td><td class="num">1,722,562</td><td class="num">1,705,968</td><td class="num">1,052,672</td><td class="num">16,594</td><td class="num">9,536</td></tr><tr><td>2026-02-09</td><td class="num">3</td><td class="num">8,276,308</td><td class="num">8,276,308</td><td class="num">8,233,458</td><td class="num">6,579,200</td><td class="num">42,850</td><td class="num">18,560</td></tr><tr><td>2026-02-10</td><td class="num">2</td><td class="num">110,210</td><td class="num">110,210</td><td class="num">106,170</td><td class="num">77,184</td><td class="num">4,040</td><td class="num">2,688</td></tr><tr><td>2026-02-14</td><td class="num">1</td><td class="num">18,724</td><td class="num">18,724</td><td class="num">17,236</td><td class="num">13,824</td><td class="num">1,488</td><td class="num">960</td></tr><tr><td>2026-02-18</td><td class="num">6</td><td class="num">38,042,984</td><td class="num">38,042,984</td><td class="num">37,824,219</td><td class="num">34,982,272</td><td class="num">218,765</td><td class="num">96,508</td></tr><tr><td>2026-02-19</td><td class="num">3</td><td class="num">2,374,671</td><td class="num">2,374,671</td><td class="num">2,336,358</td><td class="num">2,010,240</td><td class="num">38,313</td><td class="num">21,859</td></tr><tr><td>2026-02-20</td><td class="num">1</td><td class="num">815,392</td><td class="num">815,392</td><td class="num">793,001</td><td class="num">672,512</td><td class="num">22,391</td><td class="num">14,469</td></tr><tr><td>2026-02-22</td><td class="num">1</td><td class="num">86,970</td><td class="num">86,970</td><td class="num">85,224</td><td class="num">67,584</td><td class="num">1,746</td><td class="num">493</td></tr><tr><td>2026-02-23</td><td class="num">3</td><td class="num">1,503,367</td><td class="num">1,503,367</td><td class="num">1,490,803</td><td class="num">1,300,480</td><td class="num">12,564</td><td class="num">5,869</td></tr><tr><td>2026-02-24</td><td class="num">4</td><td class="num">915,167</td><td class="num">915,167</td><td class="num">894,983</td><td class="num">785,280</td><td class="num">20,184</td><td class="num">11,311</td></tr><tr><td>2026-02-25</td><td class="num">6</td><td class="num">1,153,635</td><td class="num">1,153,635</td><td class="num">1,129,519</td><td class="num">927,360</td><td class="num">24,116</td><td class="num">13,381</td></tr><tr><td>2026-02-26</td><td class="num">4</td><td class="num">4,842,727</td><td class="num">4,842,727</td><td class="num">4,769,518</td><td class="num">4,068,224</td><td class="num">73,209</td><td class="num">29,303</td></tr><tr><td>2026-02-28</td><td class="num">2</td><td class="num">203,849</td><td class="num">203,849</td><td class="num">196,188</td><td class="num">170,880</td><td class="num">7,661</td><td class="num">5,165</td></tr><tr><td>2026-03-01</td><td class="num">1</td><td class="num">144,226</td><td class="num">144,226</td><td class="num">139,396</td><td class="num">81,280</td><td class="num">4,830</td><td class="num">3,606</td></tr><tr><td>2026-03-02</td><td class="num">11</td><td class="num">1,628,800</td><td class="num">1,628,800</td><td class="num">1,593,771</td><td class="num">1,470,208</td><td class="num">35,029</td><td class="num">18,398</td></tr><tr><td>2026-03-03</td><td class="num">4</td><td class="num">1,176,373</td><td class="num">1,176,373</td><td class="num">1,157,419</td><td class="num">1,009,024</td><td class="num">18,954</td><td class="num">10,514</td></tr><tr><td>2026-03-05</td><td class="num">4</td><td class="num">1,751,326</td><td class="num">1,751,326</td><td class="num">1,725,852</td><td class="num">1,489,152</td><td class="num">25,474</td><td class="num">15,895</td></tr><tr><td>2026-03-06</td><td class="num">14</td><td class="num">3,427,861</td><td class="num">3,427,861</td><td class="num">3,348,617</td><td class="num">2,956,288</td><td class="num">79,244</td><td class="num">56,569</td></tr><tr><td>2026-03-10</td><td class="num">9</td><td class="num">2,482,191</td><td class="num">2,482,191</td><td class="num">2,423,969</td><td class="num">2,024,448</td><td class="num">58,222</td><td class="num">43,369</td></tr><tr><td>2026-03-11</td><td class="num">5</td><td class="num">707,822</td><td class="num">707,822</td><td class="num">681,540</td><td class="num">562,944</td><td class="num">26,282</td><td class="num">18,943</td></tr><tr><td>2026-03-12</td><td class="num">18</td><td class="num">103,444,689</td><td class="num">103,444,689</td><td class="num">102,734,723</td><td class="num">89,554,560</td><td class="num">709,966</td><td class="num">340,105</td></tr><tr><td>2026-03-13</td><td class="num">7</td><td class="num">68,599,649</td><td class="num">68,599,649</td><td class="num">68,188,511</td><td class="num">55,110,528</td><td class="num">411,138</td><td class="num">185,043</td></tr><tr><td>2026-03-15</td><td class="num">6</td><td class="num">972,313</td><td class="num">972,313</td><td class="num">952,374</td><td class="num">838,912</td><td class="num">19,939</td><td class="num">13,994</td></tr><tr><td>2026-03-16</td><td class="num">8</td><td class="num">5,367,296</td><td class="num">5,367,296</td><td class="num">5,288,510</td><td class="num">4,711,680</td><td class="num">78,786</td><td class="num">38,822</td></tr><tr><td>2026-03-17</td><td class="num">1</td><td class="num">3,009,062</td><td class="num">3,009,062</td><td class="num">2,988,236</td><td class="num">2,400,000</td><td class="num">20,826</td><td class="num">9,320</td></tr><tr><td>2026-03-19</td><td class="num">6</td><td class="num">5,953,315</td><td class="num">5,953,315</td><td class="num">5,903,652</td><td class="num">5,102,208</td><td class="num">49,663</td><td class="num">7,583</td></tr><tr><td>2026-03-20</td><td class="num">9</td><td class="num">14,247,345</td><td class="num">14,247,345</td><td class="num">14,098,575</td><td class="num">12,846,592</td><td class="num">148,770</td><td class="num">26,244</td></tr><tr><td>2026-03-22</td><td class="num">1</td><td class="num">3,317,062</td><td class="num">3,317,062</td><td class="num">3,305,352</td><td class="num">2,819,456</td><td class="num">11,710</td><td class="num">2,378</td></tr><tr><td>2026-03-24</td><td class="num">6</td><td class="num">21,773,327</td><td class="num">21,773,327</td><td class="num">21,545,181</td><td class="num">18,719,872</td><td class="num">228,146</td><td class="num">28,934</td></tr><tr><td>2026-03-25</td><td class="num">2</td><td class="num">15,794,732</td><td class="num">15,794,732</td><td class="num">15,689,027</td><td class="num">14,278,272</td><td class="num">105,705</td><td class="num">14,028</td></tr><tr><td>2026-03-26</td><td class="num">4</td><td class="num">17,475,352</td><td class="num">17,475,352</td><td class="num">17,365,616</td><td class="num">16,159,360</td><td class="num">109,736</td><td class="num">11,644</td></tr><tr><td>2026-03-27</td><td class="num">1</td><td class="num">98,877</td><td class="num">98,877</td><td class="num">97,169</td><td class="num">71,552</td><td class="num">1,708</td><td class="num">604</td></tr><tr><td>2026-03-28</td><td class="num">3</td><td class="num">7,712,399</td><td class="num">7,712,399</td><td class="num">7,664,563</td><td class="num">7,005,440</td><td class="num">47,836</td><td class="num">13,515</td></tr><tr><td>2026-03-31</td><td class="num">1</td><td class="num">0</td><td class="num">0</td><td class="num">0</td><td class="num">0</td><td class="num">0</td><td class="num">0</td></tr><tr><td>2026-04-01</td><td class="num">3</td><td class="num">25,508,023</td><td class="num">25,508,023</td><td class="num">25,350,746</td><td class="num">20,315,904</td><td class="num">157,277</td><td class="num">37,958</td></tr><tr><td>2026-04-02</td><td class="num">4</td><td class="num">17,199,934</td><td class="num">17,199,934</td><td class="num">17,062,790</td><td class="num">14,398,848</td><td class="num">137,144</td><td class="num">35,101</td></tr><tr><td>2026-04-04</td><td class="num">3</td><td class="num">46,566,280</td><td class="num">46,566,280</td><td class="num">46,287,856</td><td class="num">41,528,704</td><td class="num">278,424</td><td class="num">75,164</td></tr><tr><td>2026-04-05</td><td class="num">6</td><td class="num">39,855,513</td><td class="num">39,855,513</td><td class="num">39,651,697</td><td class="num">33,805,568</td><td class="num">203,816</td><td class="num">50,687</td></tr><tr><td>2026-04-06</td><td class="num">9</td><td class="num">65,364,640</td><td class="num">65,364,640</td><td class="num">64,956,269</td><td class="num">56,659,584</td><td class="num">408,371</td><td class="num">98,417</td></tr><tr><td>2026-04-08</td><td class="num">7</td><td class="num">28,703,787</td><td class="num">28,703,787</td><td class="num">28,511,836</td><td class="num">23,291,904</td><td class="num">191,951</td><td class="num">61,081</td></tr><tr><td>2026-04-10</td><td class="num">2</td><td class="num">6,955,652</td><td class="num">6,955,652</td><td class="num">6,911,550</td><td class="num">5,532,928</td><td class="num">44,102</td><td class="num">11,076</td></tr><tr><td>2026-04-11</td><td class="num">7</td><td class="num">40,151,055</td><td class="num">40,151,055</td><td class="num">40,010,387</td><td class="num">37,590,016</td><td class="num">140,668</td><td class="num">44,009</td></tr><tr><td>2026-04-12</td><td class="num">24</td><td class="num">119,779,328</td><td class="num">119,779,328</td><td class="num">119,335,097</td><td class="num">114,489,472</td><td class="num">444,231</td><td class="num">126,296</td></tr><tr><td>2026-04-13</td><td class="num">2</td><td class="num">44,278,404</td><td class="num">44,278,404</td><td class="num">44,178,204</td><td class="num">41,139,200</td><td class="num">100,200</td><td class="num">16,762</td></tr><tr><td>2026-04-14</td><td class="num">4</td><td class="num">8,627,447</td><td class="num">8,627,447</td><td class="num">8,582,567</td><td class="num">7,647,232</td><td class="num">44,880</td><td class="num">13,293</td></tr><tr><td>2026-04-16</td><td class="num">3</td><td class="num">59,357,456</td><td class="num">59,357,456</td><td class="num">59,092,558</td><td class="num">56,559,360</td><td class="num">264,898</td><td class="num">125,030</td></tr><tr><td>2026-04-20</td><td class="num">1</td><td class="num">13,711,641</td><td class="num">13,711,641</td><td class="num">13,653,855</td><td class="num">13,032,832</td><td class="num">57,786</td><td class="num">12,196</td></tr><tr><td>2026-04-21</td><td class="num">115</td><td class="num">300,116,344</td><td class="num">300,116,344</td><td class="num">298,325,385</td><td class="num">276,096,768</td><td class="num">1,790,959</td><td class="num">610,982</td></tr><tr><td>2026-04-22</td><td class="num">14</td><td class="num">22,059,804</td><td class="num">22,059,804</td><td class="num">21,867,477</td><td class="num">19,655,296</td><td class="num">192,327</td><td class="num">71,510</td></tr></tbody></table></div></section>
|
| 139 |
+
<section><h2>Weekly Tokens</h2><div class="table-wrap"><table><thead><tr><th>Label</th><th>Sessions</th><th>Tokens</th><th>Rollout total</th><th>Input</th><th>Cached input</th><th>Output</th><th>Reasoning</th></tr></thead><tbody><tr><td>2026-W06</td><td class="num">14</td><td class="num">79,547,371</td><td class="num">79,547,371</td><td class="num">79,116,105</td><td class="num">67,535,360</td><td class="num">431,266</td><td class="num">187,904</td></tr><tr><td>2026-W07</td><td class="num">6</td><td class="num">8,405,242</td><td class="num">8,405,242</td><td class="num">8,356,864</td><td class="num">6,670,208</td><td class="num">48,378</td><td class="num">22,208</td></tr><tr><td>2026-W08</td><td class="num">11</td><td class="num">41,320,017</td><td class="num">41,320,017</td><td class="num">41,038,802</td><td class="num">37,732,608</td><td class="num">281,215</td><td class="num">133,329</td></tr><tr><td>2026-W09</td><td class="num">20</td><td class="num">8,762,971</td><td class="num">8,762,971</td><td class="num">8,620,407</td><td class="num">7,333,504</td><td class="num">142,564</td><td class="num">68,635</td></tr><tr><td>2026-W10</td><td class="num">33</td><td class="num">7,984,360</td><td class="num">7,984,360</td><td class="num">7,825,659</td><td class="num">6,924,672</td><td class="num">158,701</td><td class="num">101,376</td></tr><tr><td>2026-W11</td><td class="num">45</td><td class="num">176,206,664</td><td class="num">176,206,664</td><td class="num">174,981,117</td><td class="num">148,091,392</td><td class="num">1,225,547</td><td class="num">601,454</td></tr><tr><td>2026-W12</td><td class="num">25</td><td class="num">31,894,080</td><td class="num">31,894,080</td><td class="num">31,584,325</td><td class="num">27,879,936</td><td class="num">309,755</td><td class="num">84,347</td></tr><tr><td>2026-W13</td><td class="num">16</td><td class="num">62,854,687</td><td class="num">62,854,687</td><td class="num">62,361,556</td><td class="num">56,234,496</td><td class="num">493,131</td><td class="num">68,725</td></tr><tr><td>2026-W14</td><td class="num">17</td><td class="num">129,129,750</td><td class="num">129,129,750</td><td class="num">128,353,089</td><td class="num">110,049,024</td><td class="num">776,661</td><td class="num">198,910</td></tr><tr><td>2026-W15</td><td class="num">49</td><td class="num">260,954,462</td><td class="num">260,954,462</td><td class="num">259,725,139</td><td class="num">237,563,904</td><td class="num">1,229,323</td><td class="num">340,879</td></tr><tr><td>2026-W16</td><td class="num">9</td><td class="num">112,263,307</td><td class="num">112,263,307</td><td class="num">111,853,329</td><td class="num">105,345,792</td><td class="num">409,978</td><td class="num">155,085</td></tr><tr><td>2026-W17</td><td class="num">130</td><td class="num">335,887,789</td><td class="num">335,887,789</td><td class="num">333,846,717</td><td class="num">308,784,896</td><td class="num">2,041,072</td><td class="num">694,688</td></tr></tbody></table></div></section>
|
| 140 |
+
<section><h2>Tokens By Cwd</h2><div class="table-wrap"><table><thead><tr><th>Label</th><th>Sessions</th><th>Tokens</th><th>Rollout total</th><th>Input</th><th>Cached input</th><th>Output</th><th>Reasoning</th></tr></thead><tbody><tr><td>~/Projekte/HeumandenParty</td><td class="num">25</td><td class="num">147,920,810</td><td class="num">147,920,810</td><td class="num">147,263,059</td><td class="num">135,344,768</td><td class="num">657,751</td><td class="num">224,690</td></tr><tr><td>~</td><td class="num">65</td><td class="num">143,305,952</td><td class="num">143,305,952</td><td class="num">142,271,611</td><td class="num">118,259,584</td><td class="num">1,034,341</td><td class="num">411,954</td></tr><tr><td>~/Projekte/UEBER_AGENT</td><td class="num">14</td><td class="num">95,265,645</td><td class="num">95,265,645</td><td class="num">94,690,320</td><td class="num">82,054,784</td><td class="num">575,325</td><td class="num">136,176</td></tr><tr><td>~/Projekte/PromptBoost</td><td class="num">40</td><td class="num">91,369,695</td><td class="num">91,369,695</td><td class="num">90,715,571</td><td class="num">84,423,552</td><td class="num">654,124</td><td class="num">254,702</td></tr><tr><td>~/Projekte/Zentrale</td><td class="num">19</td><td class="num">86,591,689</td><td class="num">86,591,689</td><td class="num">86,233,084</td><td class="num">82,599,424</td><td class="num">358,605</td><td class="num">98,470</td></tr><tr><td>~/Projekte/Sidecar-V7</td><td class="num">9</td><td class="num">84,675,641</td><td class="num">84,675,641</td><td class="num">84,245,938</td><td class="num">74,833,280</td><td class="num">429,703</td><td class="num">197,775</td></tr><tr><td>~/Projekte</td><td class="num">28</td><td class="num">83,595,490</td><td class="num">83,595,490</td><td class="num">83,172,046</td><td class="num">74,665,344</td><td class="num">423,444</td><td class="num">112,523</td></tr><tr><td>~/Dokumente/Pläne</td><td class="num">4</td><td class="num">66,513,874</td><td class="num">66,513,874</td><td class="num">66,247,523</td><td class="num">57,384,832</td><td class="num">266,351</td><td class="num">83,776</td></tr><tr><td>~/Projekte/FirstRealHarnessEvaluation_KarpathiesMD</td><td class="num">2</td><td class="num">59,357,456</td><td class="num">59,357,456</td><td class="num">59,092,558</td><td class="num">56,559,360</td><td class="num">264,898</td><td class="num">125,030</td></tr><tr><td>~/clawd</td><td class="num">4</td><td class="num">49,462,644</td><td class="num">49,462,644</td><td class="num">49,155,998</td><td class="num">43,810,432</td><td class="num">306,646</td><td class="num">91,996</td></tr><tr><td>~/DataEngeeneeringKEEPA</td><td class="num">6</td><td class="num">46,940,456</td><td class="num">46,940,456</td><td class="num">46,696,473</td><td class="num">41,869,440</td><td class="num">243,983</td><td class="num">105,385</td></tr><tr><td>~/SetUP/Monitor_my_Monitors</td><td class="num">3</td><td class="num">37,573,267</td><td class="num">37,573,267</td><td class="num">37,477,005</td><td class="num">36,243,584</td><td class="num">96,262</td><td class="num">33,239</td></tr><tr><td>~/Projekte/PromptBoost/personalPromptBoost</td><td class="num">13</td><td class="num">22,802,481</td><td class="num">22,802,481</td><td class="num">22,611,147</td><td class="num">20,876,160</td><td class="num">191,334</td><td class="num">57,401</td></tr><tr><td>~/Projekte/Jobs_Selbständigkeit_Geldverdienen/AgentTestUniSupport</td><td class="num">2</td><td class="num">19,887,811</td><td class="num">19,887,811</td><td class="num">19,747,782</td><td class="num">16,509,568</td><td class="num">140,029</td><td class="num">26,289</td></tr><tr><td>~/Projekte/PromptGarage</td><td class="num">1</td><td class="num">19,452,133</td><td class="num">19,452,133</td><td class="num">19,394,544</td><td class="num">18,764,544</td><td class="num">57,589</td><td class="num">18,018</td></tr><tr><td>~/Projekte/Sonnenuhr</td><td class="num">7</td><td class="num">18,900,534</td><td class="num">18,900,534</td><td class="num">18,712,969</td><td class="num">16,705,024</td><td class="num">187,565</td><td class="num">107,257</td></tr><tr><td>~/Projekte/PseudoLogikPyhthonCPP</td><td class="num">2</td><td class="num">16,329,762</td><td class="num">16,329,762</td><td class="num">16,254,080</td><td class="num">15,190,656</td><td class="num">75,682</td><td class="num">20,994</td></tr><tr><td>~/Projekte/Jobs_Selbständigkeit_Geldverdienen/aidvance-proposal</td><td class="num">2</td><td class="num">15,236,493</td><td class="num">15,236,493</td><td class="num">15,153,630</td><td class="num">14,106,752</td><td class="num">82,863</td><td class="num">7,162</td></tr><tr><td>~/Projekte/KomandoZentral</td><td class="num">1</td><td class="num">10,463,900</td><td class="num">10,463,900</td><td class="num">10,379,137</td><td class="num">9,012,224</td><td class="num">84,763</td><td class="num">11,443</td></tr><tr><td>~/Projekte/PortfolioTimeline</td><td class="num">1</td><td class="num">10,249,632</td><td class="num">10,249,632</td><td class="num">10,174,172</td><td class="num">9,088,640</td><td class="num">75,460</td><td class="num">10,612</td></tr><tr><td>~/.claude</td><td class="num">3</td><td class="num">9,009,529</td><td class="num">9,009,529</td><td class="num">8,957,065</td><td class="num">8,283,264</td><td class="num">52,464</td><td class="num">16,602</td></tr><tr><td>~/ProjekteV2/CodexDashboard</td><td class="num">2</td><td class="num">8,661,587</td><td class="num">8,661,587</td><td class="num">8,596,572</td><td class="num">7,898,368</td><td class="num">65,015</td><td class="num">10,400</td></tr><tr><td>~/Projekte/Sidecar-V8</td><td class="num">1</td><td class="num">8,647,140</td><td class="num">8,647,140</td><td class="num">8,563,822</td><td class="num">6,135,040</td><td class="num">83,318</td><td class="num">36,118</td></tr><tr><td>~/Projekte/Amazon</td><td class="num">2</td><td class="num">8,419,747</td><td class="num">8,419,747</td><td class="num">8,378,736</td><td class="num">7,515,136</td><td class="num">41,011</td><td class="num">12,014</td></tr><tr><td>~/Projekte/AgentArena</td><td class="num">13</td><td class="num">7,849,846</td><td class="num">7,849,846</td><td class="num">7,764,724</td><td class="num">7,166,464</td><td class="num">85,122</td><td class="num">43,235</td></tr><tr><td>~/Codex</td><td class="num">3</td><td class="num">7,099,187</td><td class="num">7,099,187</td><td class="num">7,047,299</td><td class="num">6,103,680</td><td class="num">51,888</td><td class="num">14,249</td></tr><tr><td>~/Projekte/NasaCode/Autoresearch</td><td class="num">1</td><td class="num">6,896,321</td><td class="num">6,896,321</td><td class="num">6,864,934</td><td class="num">6,334,464</td><td class="num">31,387</td><td class="num">8,024</td></tr><tr><td>~/Projekte/MultiHarnessStudio</td><td class="num">6</td><td class="num">6,580,156</td><td class="num">6,580,156</td><td class="num">6,497,175</td><td class="num">4,835,584</td><td class="num">82,981</td><td class="num">24,300</td></tr><tr><td>~/Projekte/BahnAgent</td><td class="num">3</td><td class="num">5,287,171</td><td class="num">5,287,171</td><td class="num">5,247,750</td><td class="num">4,559,872</td><td class="num">39,421</td><td class="num">7,976</td></tr><tr><td>~/Projekte/MetaMetaMeta</td><td class="num">1</td><td class="num">5,180,427</td><td class="num">5,180,427</td><td class="num">5,107,914</td><td class="num">4,216,576</td><td class="num">72,513</td><td class="num">5,337</td></tr><tr><td>~/Projekte/ClaudeCodePanel</td><td class="num">21</td><td class="num">5,004,177</td><td class="num">5,004,177</td><td class="num">4,896,768</td><td class="num">4,237,568</td><td class="num">107,409</td><td class="num">70,091</td></tr><tr><td>~/ProjekteV2/CodexWebsiteSamuelClaudecode</td><td class="num">6</td><td class="num">4,856,550</td><td class="num">4,856,550</td><td class="num">4,797,674</td><td class="num">4,300,544</td><td class="num">58,876</td><td class="num">11,598</td></tr><tr><td>~/Projekte/Jobs_Selbständigkeit_Geldverdienen/AgentTestUniSupport/docs</td><td class="num">1</td><td class="num">4,068,531</td><td class="num">4,068,531</td><td class="num">4,048,457</td><td class="num">3,692,928</td><td class="num">20,074</td><td class="num">5,899</td></tr><tr><td>~/Projekte/Sidecar-ng</td><td class="num">2</td><td class="num">3,778,526</td><td class="num">3,778,526</td><td class="num">3,753,634</td><td class="num">3,067,776</td><td class="num">24,892</td><td class="num">10,022</td></tr><tr><td>~/Projekte/BahnAgent/HD-St.Anton</td><td class="num">1</td><td class="num">3,588,293</td><td class="num">3,588,293</td><td class="num">3,566,427</td><td class="num">3,453,056</td><td class="num">21,866</td><td class="num">9,190</td></tr><tr><td>~/Projekte/Sidecar-ng-dashboard</td><td class="num">1</td><td class="num">3,565,535</td><td class="num">3,565,535</td><td class="num">3,533,244</td><td class="num">3,355,264</td><td class="num">32,291</td><td class="num">4,937</td></tr><tr><td>~/.hermes</td><td class="num">2</td><td class="num">3,317,062</td><td class="num">3,317,062</td><td class="num">3,305,352</td><td class="num">2,819,456</td><td class="num">11,710</td><td class="num">2,378</td></tr><tr><td>~/Projekte/schloss_PDF</td><td class="num">1</td><td class="num">3,245,804</td><td class="num">3,245,804</td><td class="num">3,229,768</td><td class="num">3,069,824</td><td class="num">16,036</td><td class="num">4,866</td></tr><tr><td>~/ClaudesReich</td><td class="num">3</td><td class="num">2,206,746</td><td class="num">2,206,746</td><td class="num">2,139,356</td><td class="num">1,719,296</td><td class="num">67,390</td><td class="num">51,059</td></tr><tr><td>~/Dokumente/durchstarten</td><td class="num">1</td><td class="num">2,177,869</td><td class="num">2,177,869</td><td class="num">2,165,792</td><td class="num">1,844,224</td><td class="num">12,077</td><td class="num">3,264</td></tr><tr><td>~/Projekte/Sidecar-V7-V2</td><td class="num">1</td><td class="num">1,906,923</td><td class="num">1,906,923</td><td class="num">1,893,090</td><td class="num">1,818,624</td><td class="num">13,833</td><td class="num">9,278</td></tr><tr><td>~/abgabe</td><td class="num">3</td><td class="num">1,904,474</td><td class="num">1,904,474</td><td class="num">1,885,225</td><td class="num">1,680,128</td><td class="num">19,249</td><td class="num">9,211</td></tr><tr><td>~/Projekte/Codex_Usage_Profil</td><td class="num">1</td><td class="num">1,863,742</td><td class="num">1,863,742</td><td class="num">1,839,771</td><td class="num">1,688,192</td><td class="num">23,971</td><td class="num">6,446</td></tr><tr><td>~/Projekte/AgentIDE</td><td class="num">3</td><td class="num">1,595,515</td><td class="num">1,595,515</td><td class="num">1,563,469</td><td class="num">1,397,760</td><td class="num">32,046</td><td class="num">22,910</td></tr><tr><td>~/Projekte/Jobs_Selbständigkeit_Geldverdienen</td><td class="num">1</td><td class="num">1,482,737</td><td class="num">1,482,737</td><td class="num">1,459,527</td><td class="num">1,327,488</td><td class="num">23,210</td><td class="num">3,945</td></tr><tr><td>~/.claude/usage</td><td class="num">1</td><td class="num">1,205,428</td><td class="num">1,205,428</td><td class="num">1,179,696</td><td class="num">1,085,696</td><td class="num">25,732</td><td class="num">8,416</td></tr><tr><td>~/DataEngeeneeringKEEPA/KeepaProjectsforDataEngeneering3BranchesMerge</td><td class="num">6</td><td class="num">1,152,226</td><td class="num">1,152,226</td><td class="num">1,129,759</td><td class="num">927,360</td><td class="num">22,467</td><td class="num">11,740</td></tr><tr><td>~/Projekte/ACPcodex</td><td class="num">1</td><td class="num">1,059,170</td><td class="num">1,059,170</td><td class="num">1,043,792</td><td class="num">910,848</td><td class="num">15,378</td><td class="num">8,018</td></tr><tr><td>~/Projekte/NasaCode</td><td class="num">1</td><td class="num">985,209</td><td class="num">985,209</td><td class="num">970,106</td><td class="num">897,408</td><td class="num">15,103</td><td class="num">1,784</td></tr><tr><td>~/Projekte/Kaggle5dayAgent</td><td class="num">2</td><td class="num">913,047</td><td class="num">913,047</td><td class="num">897,573</td><td class="num">686,592</td><td class="num">15,474</td><td class="num">5,673</td></tr><tr><td>~/ProjekteV2/CodexEval2</td><td class="num">1</td><td class="num">729,208</td><td class="num">729,208</td><td class="num">704,329</td><td class="num">647,680</td><td class="num">24,879</td><td class="num">4,246</td></tr><tr><td>~/Meta</td><td class="num">1</td><td class="num">718,880</td><td class="num">718,880</td><td class="num">707,059</td><td class="num">528,512</td><td class="num">11,821</td><td class="num">4,379</td></tr><tr><td>~/Projekte/HarnessEcosystem</td><td class="num">1</td><td class="num">600,507</td><td class="num">600,507</td><td class="num">592,621</td><td class="num">502,656</td><td class="num">7,886</td><td class="num">1,399</td></tr><tr><td>~/Projekte/StudyAgent</td><td class="num">1</td><td class="num">511,185</td><td class="num">511,185</td><td class="num">501,306</td><td class="num">464,768</td><td class="num">9,879</td><td class="num">7,380</td></tr><tr><td>~/Projekte/ShortcutCounter</td><td class="num">1</td><td class="num">441,229</td><td class="num">441,229</td><td class="num">435,073</td><td class="num">398,976</td><td class="num">6,156</td><td class="num">3,416</td></tr><tr><td>~/Projekte/TypoTuner</td><td class="num">3</td><td class="num">430,804</td><td class="num">430,804</td><td class="num">412,494</td><td class="num">324,992</td><td class="num">18,310</td><td class="num">13,352</td></tr><tr><td>~/Projekte/SandrasWritingWorld</td><td class="num">3</td><td class="num">347,623</td><td class="num">347,623</td><td class="num">340,146</td><td class="num">290,560</td><td class="num">7,477</td><td class="num">4,607</td></tr><tr><td>~/CodexReich</td><td class="num">2</td><td class="num">282,250</td><td class="num">282,250</td><td class="num">271,237</td><td class="num">254,208</td><td class="num">11,013</td><td class="num">8,192</td></tr><tr><td>~/Projekte/Sidecar</td><td class="num">1</td><td class="num">251,167</td><td class="num">251,167</td><td class="num">245,022</td><td class="num">213,504</td><td class="num">6,145</td><td class="num">4,675</td></tr><tr><td>~/Projekte/PromptEngeneering</td><td class="num">2</td><td class="num">207,700</td><td class="num">207,700</td><td class="num">203,831</td><td class="num">132,096</td><td class="num">3,869</td><td class="num">1,279</td></tr><tr><td>~/ClaudesReich/SessionBrowser</td><td class="num">2</td><td class="num">203,849</td><td class="num">203,849</td><td class="num">196,188</td><td class="num">170,880</td><td class="num">7,661</td><td class="num">5,165</td></tr><tr><td>~/Projekte/Sidecar-V7-Lite</td><td class="num">1</td><td class="num">197,279</td><td class="num">197,279</td><td class="num">190,627</td><td class="num">177,792</td><td class="num">6,652</td><td class="num">4,599</td></tr><tr><td>~/Projekte/FireTracker</td><td class="num">2</td><td class="num">191,892</td><td class="num">191,892</td><td class="num">184,419</td><td class="num">153,344</td><td class="num">7,473</td><td class="num">5,715</td></tr><tr><td>~/Bilder/Anzug/Logo</td><td class="num">1</td><td class="num">141,042</td><td class="num">141,042</td><td class="num">138,537</td><td class="num">102,016</td><td class="num">2,505</td><td class="num">1,280</td></tr><tr><td>~/DataEngeeneeringKEEPA/VomProfPDF</td><td class="num">1</td><td class="num">135,655</td><td class="num">135,655</td><td class="num">131,074</td><td class="num">119,168</td><td class="num">4,581</td><td class="num">2,463</td></tr><tr><td>~/Orderformyaistuff</td><td class="num">1</td><td class="num">132,215</td><td class="num">132,215</td><td class="num">131,214</td><td class="num">112,128</td><td class="num">1,001</td><td class="num">64</td></tr><tr><td>~/OrdnungvonGedanken/git</td><td class="num">1</td><td class="num">113,347</td><td class="num">113,347</td><td class="num">108,699</td><td class="num">96,384</td><td class="num">4,648</td><td class="num">1,633</td></tr><tr><td>~/ClaudesReich/Visualisierung</td><td class="num">3</td><td class="num">86,970</td><td class="num">86,970</td><td class="num">85,224</td><td class="num">67,584</td><td class="num">1,746</td><td class="num">493</td></tr><tr><td>~/Projekte/MyAIGame</td><td class="num">2</td><td class="num">72,823</td><td class="num">72,823</td><td class="num">62,967</td><td class="num">51,328</td><td class="num">9,856</td><td class="num">6,964</td></tr><tr><td>/tmp/MyAIGame</td><td class="num">1</td><td class="num">11,035</td><td class="num">11,035</td><td class="num">7,924</td><td class="num">6,784</td><td class="num">3,111</td><td class="num">2,367</td></tr><tr><td>~/SetUP</td><td class="num">1</td><td class="num">0</td><td class="num">0</td><td class="num">0</td><td class="num">0</td><td class="num">0</td><td class="num">0</td></tr><tr><td>~/Projekte/HarnessEcosystem/sidebyside</td><td class="num">1</td><td class="num">0</td><td class="num">0</td><td class="num">0</td><td class="num">0</td><td class="num">0</td><td class="num">0</td></tr></tbody></table></div></section>
|
| 141 |
+
<section><h2>Tokens By Model</h2><div class="table-wrap"><table><thead><tr><th>Label</th><th>Sessions</th><th>Tokens</th><th>Rollout total</th><th>Input</th><th>Cached input</th><th>Output</th><th>Reasoning</th></tr></thead><tbody><tr><td>gpt-5.4</td><td class="num">190</td><td class="num">1,002,621,471</td><td class="num">1,002,621,471</td><td class="num">997,085,786</td><td class="num">895,809,024</td><td class="num">5,535,685</td><td class="num">1,652,172</td></tr><tr><td>gpt-5.4-mini</td><td class="num">64</td><td class="num">94,242,789</td><td class="num">94,242,789</td><td class="num">93,515,945</td><td class="num">87,385,344</td><td class="num">726,844</td><td class="num">349,506</td></tr><tr><td>gpt-5.1-codex-max</td><td class="num">14</td><td class="num">86,258,755</td><td class="num">86,258,755</td><td class="num">85,848,562</td><td class="num">72,738,816</td><td class="num">410,193</td><td class="num">157,571</td></tr><tr><td>gpt-5.3-codex</td><td class="num">97</td><td class="num">63,196,733</td><td class="num">63,196,733</td><td class="num">62,443,450</td><td class="num">56,599,040</td><td class="num">753,283</td><td class="num">432,430</td></tr><tr><td>gpt-5.1-codex-mini</td><td class="num">2</td><td class="num">4,583,943</td><td class="num">4,583,943</td><td class="num">4,546,444</td><td class="num">4,075,904</td><td class="num">37,499</td><td class="num">7,045</td></tr><tr><td>gpt-5.2-codex</td><td class="num">5</td><td class="num">4,307,009</td><td class="num">4,307,009</td><td class="num">4,222,922</td><td class="num">3,537,664</td><td class="num">84,087</td><td class="num">58,816</td></tr><tr><td>unknown</td><td class="num">3</td><td class="num">0</td><td class="num">0</td><td class="num">0</td><td class="num">0</td><td class="num">0</td><td class="num">0</td></tr></tbody></table></div></section>
|
| 142 |
+
<section><h2>Tokens By Role</h2><div class="table-wrap"><table><thead><tr><th>Label</th><th>Sessions</th><th>Tokens</th><th>Rollout total</th><th>Input</th><th>Cached input</th><th>Output</th><th>Reasoning</th></tr></thead><tbody><tr><td>main</td><td class="num">240</td><td class="num">1,162,370,493</td><td class="num">1,162,370,493</td><td class="num">1,155,950,486</td><td class="num">1,039,647,488</td><td class="num">6,420,007</td><td class="num">2,223,740</td></tr><tr><td>unknown</td><td class="num">17</td><td class="num">31,239,166</td><td class="num">31,239,166</td><td class="num">30,924,883</td><td class="num">27,394,176</td><td class="num">314,283</td><td class="num">116,098</td></tr><tr><td>worker</td><td class="num">18</td><td class="num">30,777,412</td><td class="num">30,777,412</td><td class="num">30,458,569</td><td class="num">28,003,584</td><td class="num">318,843</td><td class="num">108,953</td></tr><tr><td>explorer</td><td class="num">94</td><td class="num">30,734,460</td><td class="num">30,734,460</td><td class="num">30,240,125</td><td class="num">25,049,600</td><td class="num">494,335</td><td class="num">208,680</td></tr><tr><td>default</td><td class="num">6</td><td class="num">89,169</td><td class="num">89,169</td><td class="num">89,046</td><td class="num">50,944</td><td class="num">123</td><td class="num">69</td></tr></tbody></table></div></section>
|
| 143 |
+
<section><h2>Main Vs Subagent</h2><div class="table-wrap"><table><thead><tr><th>Label</th><th>Sessions</th><th>Tokens</th><th>Rollout total</th><th>Input</th><th>Cached input</th><th>Output</th><th>Reasoning</th></tr></thead><tbody><tr><td>main</td><td class="num">250</td><td class="num">1,170,627,399</td><td class="num">1,170,627,399</td><td class="num">1,164,127,535</td><td class="num">1,046,924,928</td><td class="num">6,499,864</td><td class="num">2,236,967</td></tr><tr><td>subagent</td><td class="num">125</td><td class="num">84,583,301</td><td class="num">84,583,301</td><td class="num">83,535,574</td><td class="num">73,220,864</td><td class="num">1,047,727</td><td class="num">420,573</td></tr></tbody></table></div></section>
|
| 144 |
+
<section><h2>Top Sessions</h2><div class="table-wrap"><table><thead><tr><th>Created</th><th>Tokens</th><th>Kind</th><th>Model</th><th>Role</th><th>Cwd</th><th>Session</th><th>Rollout</th></tr></thead><tbody><tr><td>2026-04-16 13:01</td><td class="num">47,959,797</td><td>main</td><td>gpt-5.4-mini</td><td>main</td><td>~/Projekte/FirstRealHarnessEvaluation_KarpathiesMD</td><td>019d95f4-0198-7e10-9c95-ecd79e771e27</td><td>/home/smlflg/.codex/sessions/2026/04/16/rollout-2026-04-16T13-01-29-019d95f4-0198-7e10-9c95-ecd79e771e27.jsonl</td></tr><tr><td>2026-04-04 16:27</td><td class="num">45,688,987</td><td>main</td><td>gpt-5.4</td><td>main</td><td>~/clawd</td><td>019d58e4-046a-7c10-a832-f8c706647456</td><td>/home/smlflg/.codex/sessions/2026/04/04/rollout-2026-04-04T16-27-11-019d58e4-046a-7c10-a832-f8c706647456.jsonl</td></tr><tr><td>2026-04-13 07:09</td><td class="num">43,897,402</td><td>main</td><td>gpt-5.4</td><td>main</td><td>~/Projekte/HeumandenParty</td><td>019d853e-b868-7053-bb8c-630df03c6eea</td><td>/home/smlflg/.codex/sessions/2026/04/13/rollout-2026-04-13T07-09-33-019d853e-b868-7053-bb8c-630df03c6eea.jsonl</td></tr><tr><td>2026-03-13 12:03</td><td class="num">42,283,906</td><td>main</td><td>gpt-5.4</td><td>main</td><td>~/Projekte/Sidecar-V7</td><td>019ce6dd-5a1c-7fe3-a300-b98983ae4bb8</td><td>/home/smlflg/.codex/sessions/2026/03/13/rollout-2026-03-13T12-03-12-019ce6dd-5a1c-7fe3-a300-b98983ae4bb8.jsonl</td></tr><tr><td>2026-02-05 12:11</td><td class="num">40,984,928</td><td>main</td><td>gpt-5.1-codex-max</td><td>main</td><td>~/Dokumente/Pläne</td><td>019c2d80-2f19-7521-9c87-4d6be1ffc9f1</td><td>/home/smlflg/.codex/sessions/2026/02/05/rollout-2026-02-05T12-11-41-019c2d80-2f19-7521-9c87-4d6be1ffc9f1.jsonl</td></tr><tr><td>2026-03-12 00:59</td><td class="num">34,165,684</td><td>main</td><td>gpt-5.4</td><td>main</td><td>~</td><td>019cdf57-c2c6-7a92-9096-6dac18fc5177</td><td>/home/smlflg/.codex/sessions/2026/03/12/rollout-2026-03-12T00-59-56-019cdf57-c2c6-7a92-9096-6dac18fc5177.jsonl</td></tr><tr><td>2026-02-18 17:07</td><td class="num">32,848,911</td><td>main</td><td>gpt-5.3-codex</td><td>main</td><td>~/DataEngeeneeringKEEPA</td><td>019c7181-a37e-7ae2-8870-c4c16655ec52</td><td>/home/smlflg/.codex/sessions/2026/02/18/rollout-2026-02-18T17-07-27-019c7181-a37e-7ae2-8870-c4c16655ec52.jsonl</td></tr><tr><td>2026-04-21 23:03</td><td class="num">32,619,865</td><td>main</td><td>gpt-5.4</td><td>main</td><td>~/Projekte/HeumandenParty</td><td>019db1db-150f-7662-b607-30871c33af75</td><td>/home/smlflg/.codex/sessions/2026/04/21/rollout-2026-04-21T23-03-38-019db1db-150f-7662-b607-30871c33af75.jsonl</td></tr><tr><td>2026-04-05 18:49</td><td class="num">29,145,038</td><td>main</td><td>gpt-5.4</td><td>main</td><td>~/Projekte/UEBER_AGENT</td><td>019d5e8c-39f3-7db1-a48b-d4eb2b50298e</td><td>/home/smlflg/.codex/sessions/2026/04/05/rollout-2026-04-05T18-49-01-019d5e8c-39f3-7db1-a48b-d4eb2b50298e.jsonl</td></tr><tr><td>2026-04-06 12:58</td><td class="num">25,127,211</td><td>main</td><td>gpt-5.4</td><td>main</td><td>~/Projekte/UEBER_AGENT</td><td>019d6271-60b8-7621-a2c4-7a66afca9f80</td><td>/home/smlflg/.codex/sessions/2026/04/06/rollout-2026-04-06T12-58-10-019d6271-60b8-7621-a2c4-7a66afca9f80.jsonl</td></tr><tr><td>2026-02-07 19:08</td><td class="num">22,356,063</td><td>main</td><td>gpt-5.1-codex-max</td><td>main</td><td>~/Dokumente/Pläne</td><td>019c394a-8761-7823-8f7e-7457d21d79af</td><td>/home/smlflg/.codex/sessions/2026/02/07/rollout-2026-02-07T19-08-31-019c394a-8761-7823-8f7e-7457d21d79af.jsonl</td></tr><tr><td>2026-04-08 10:23</td><td class="num">22,123,631</td><td>main</td><td>gpt-5.4</td><td>main</td><td>~/Projekte/HeumandenParty</td><td>019d6c30-e1c5-7441-9ed6-afc8f2bc9861</td><td>/home/smlflg/.codex/sessions/2026/04/08/rollout-2026-04-08T10-23-56-019d6c30-e1c5-7441-9ed6-afc8f2bc9861.jsonl</td></tr><tr><td>2026-04-21 23:28</td><td class="num">21,430,259</td><td>main</td><td>gpt-5.4</td><td>main</td><td>~/Projekte/HeumandenParty</td><td>019db1f1-e994-75c0-94d8-6edc93203dd7</td><td>/home/smlflg/.codex/sessions/2026/04/21/rollout-2026-04-21T23-28-34-019db1f1-e994-75c0-94d8-6edc93203dd7.jsonl</td></tr><tr><td>2026-04-21 15:43</td><td class="num">21,410,253</td><td>main</td><td>gpt-5.4</td><td>main</td><td>~</td><td>019db048-0123-7242-89b9-d6083591212b</td><td>/home/smlflg/.codex/sessions/2026/04/21/rollout-2026-04-21T15-43-22-019db048-0123-7242-89b9-d6083591212b.jsonl</td></tr><tr><td>2026-04-21 15:31</td><td class="num">21,194,654</td><td>main</td><td>gpt-5.4</td><td>main</td><td>~/Projekte/PromptBoost</td><td>019db03d-1f96-7592-8fef-1f10125ebe0c</td><td>/home/smlflg/.codex/sessions/2026/04/21/rollout-2026-04-21T15-31-29-019db03d-1f96-7592-8fef-1f10125ebe0c.jsonl</td></tr><tr><td>2026-03-12 15:10</td><td class="num">21,018,788</td><td>main</td><td>gpt-5.4</td><td>main</td><td>~/Projekte/Sidecar-V7</td><td>019ce262-7359-7ae2-b3c1-e1c5d1a63e66</td><td>/home/smlflg/.codex/sessions/2026/03/12/rollout-2026-03-12T15-10-28-019ce262-7359-7ae2-b3c1-e1c5d1a63e66.jsonl</td></tr><tr><td>2026-04-21 15:27</td><td class="num">20,456,527</td><td>main</td><td>gpt-5.4</td><td>main</td><td>~/Projekte/PromptBoost</td><td>019db039-1b8f-7370-bab6-9e25fd16e912</td><td>/home/smlflg/.codex/sessions/2026/04/21/rollout-2026-04-21T15-27-05-019db039-1b8f-7370-bab6-9e25fd16e912.jsonl</td></tr><tr><td>2026-04-12 15:58</td><td class="num">20,372,968</td><td>main</td><td>gpt-5.4</td><td>main</td><td>~/Projekte/Zentrale</td><td>019d81fc-7347-7523-b30f-4d3ddce562e1</td><td>/home/smlflg/.codex/sessions/2026/04/12/rollout-2026-04-12T15-58-18-019d81fc-7347-7523-b30f-4d3ddce562e1.jsonl</td></tr><tr><td>2026-03-12 15:14</td><td class="num">19,745,610</td><td>main</td><td>gpt-5.4</td><td>main</td><td>~/Projekte/Sidecar-V7</td><td>019ce266-3a71-79e2-ada1-226867a34de3</td><td>/home/smlflg/.codex/sessions/2026/03/12/rollout-2026-03-12T15-14-36-019ce266-3a71-79e2-ada1-226867a34de3.jsonl</td></tr><tr><td>2026-04-21 14:53</td><td class="num">19,452,133</td><td>main</td><td>gpt-5.4</td><td>main</td><td>~/Projekte/PromptGarage</td><td>019db01a-8e1c-7560-b78f-63857f297f47</td><td>/home/smlflg/.codex/sessions/2026/04/21/rollout-2026-04-21T14-53-43-019db01a-8e1c-7560-b78f-63857f297f47.jsonl</td></tr></tbody></table></div></section>
|
| 145 |
+
<section><h2>Data Warnings</h2><ul><li><code>Malformed JSONL lines in /home/smlflg/.codex/sessions/2026/04/21/rollout-2026-04-21T18-15-04-019db0d2-e62b-78b3-b8f3-e0c70af3aa6c.jsonl: 1</code></li></ul></section>
|
| 146 |
+
</main>
|
| 147 |
+
</body>
|
| 148 |
+
</html>
|
reports/codex-usage.md
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Codex Usage Report
|
| 2 |
+
|
| 3 |
+
Generated: 2026-04-22T00:48:49+02:00
|
| 4 |
+
Timezone: `Europe/Berlin`
|
| 5 |
+
State DB: `/home/smlflg/.codex/state_5.sqlite`
|
| 6 |
+
Sessions dir: `/home/smlflg/.codex/sessions`
|
| 7 |
+
Date range: 2026-02-03 to 2026-04-22
|
| 8 |
+
|
| 9 |
+
## Summary
|
| 10 |
+
|
| 11 |
+
| Metric | Value |
|
| 12 |
+
| --- | --- |
|
| 13 |
+
| Sessions | 375 |
|
| 14 |
+
| Total tokens | 1,255,210,700 |
|
| 15 |
+
| Rollouts with token breakdown | 359 |
|
| 16 |
+
| Missing rollouts | 0 |
|
| 17 |
+
| Warnings | 1 |
|
| 18 |
+
|
| 19 |
+
## Rollout Token Breakdown
|
| 20 |
+
|
| 21 |
+
| Input | Cached input | Output | Reasoning output | Rollout total |
|
| 22 |
+
| --- | --- | --- | --- | --- |
|
| 23 |
+
| 1,247,663,109 | 1,120,145,792 | 7,547,591 | 2,657,540 | 1,255,210,700 |
|
| 24 |
+
|
| 25 |
+
## Daily Tokens
|
| 26 |
+
|
| 27 |
+
| Label | Sessions | Tokens | Rollout total | Input | Cached input | Output | Reasoning |
|
| 28 |
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
| 29 |
+
| 2026-02-03 | 4 | 2,592,334 | 2,592,334 | 2,568,243 | 2,210,560 | 24,091 | 11,520 |
|
| 30 |
+
| 2026-02-04 | 1 | 1,714,675 | 1,714,675 | 1,654,679 | 1,327,104 | 59,996 | 47,296 |
|
| 31 |
+
| 2026-02-05 | 3 | 41,998,810 | 41,998,810 | 41,824,072 | 36,333,696 | 174,738 | 62,720 |
|
| 32 |
+
| 2026-02-06 | 2 | 3,102,257 | 3,102,257 | 3,087,487 | 2,501,760 | 14,770 | 5,248 |
|
| 33 |
+
| 2026-02-07 | 3 | 28,416,733 | 28,416,733 | 28,275,656 | 24,109,568 | 141,077 | 51,584 |
|
| 34 |
+
| 2026-02-08 | 1 | 1,722,562 | 1,722,562 | 1,705,968 | 1,052,672 | 16,594 | 9,536 |
|
| 35 |
+
| 2026-02-09 | 3 | 8,276,308 | 8,276,308 | 8,233,458 | 6,579,200 | 42,850 | 18,560 |
|
| 36 |
+
| 2026-02-10 | 2 | 110,210 | 110,210 | 106,170 | 77,184 | 4,040 | 2,688 |
|
| 37 |
+
| 2026-02-14 | 1 | 18,724 | 18,724 | 17,236 | 13,824 | 1,488 | 960 |
|
| 38 |
+
| 2026-02-18 | 6 | 38,042,984 | 38,042,984 | 37,824,219 | 34,982,272 | 218,765 | 96,508 |
|
| 39 |
+
| 2026-02-19 | 3 | 2,374,671 | 2,374,671 | 2,336,358 | 2,010,240 | 38,313 | 21,859 |
|
| 40 |
+
| 2026-02-20 | 1 | 815,392 | 815,392 | 793,001 | 672,512 | 22,391 | 14,469 |
|
| 41 |
+
| 2026-02-22 | 1 | 86,970 | 86,970 | 85,224 | 67,584 | 1,746 | 493 |
|
| 42 |
+
| 2026-02-23 | 3 | 1,503,367 | 1,503,367 | 1,490,803 | 1,300,480 | 12,564 | 5,869 |
|
| 43 |
+
| 2026-02-24 | 4 | 915,167 | 915,167 | 894,983 | 785,280 | 20,184 | 11,311 |
|
| 44 |
+
| 2026-02-25 | 6 | 1,153,635 | 1,153,635 | 1,129,519 | 927,360 | 24,116 | 13,381 |
|
| 45 |
+
| 2026-02-26 | 4 | 4,842,727 | 4,842,727 | 4,769,518 | 4,068,224 | 73,209 | 29,303 |
|
| 46 |
+
| 2026-02-28 | 2 | 203,849 | 203,849 | 196,188 | 170,880 | 7,661 | 5,165 |
|
| 47 |
+
| 2026-03-01 | 1 | 144,226 | 144,226 | 139,396 | 81,280 | 4,830 | 3,606 |
|
| 48 |
+
| 2026-03-02 | 11 | 1,628,800 | 1,628,800 | 1,593,771 | 1,470,208 | 35,029 | 18,398 |
|
| 49 |
+
| 2026-03-03 | 4 | 1,176,373 | 1,176,373 | 1,157,419 | 1,009,024 | 18,954 | 10,514 |
|
| 50 |
+
| 2026-03-05 | 4 | 1,751,326 | 1,751,326 | 1,725,852 | 1,489,152 | 25,474 | 15,895 |
|
| 51 |
+
| 2026-03-06 | 14 | 3,427,861 | 3,427,861 | 3,348,617 | 2,956,288 | 79,244 | 56,569 |
|
| 52 |
+
| 2026-03-10 | 9 | 2,482,191 | 2,482,191 | 2,423,969 | 2,024,448 | 58,222 | 43,369 |
|
| 53 |
+
| 2026-03-11 | 5 | 707,822 | 707,822 | 681,540 | 562,944 | 26,282 | 18,943 |
|
| 54 |
+
| 2026-03-12 | 18 | 103,444,689 | 103,444,689 | 102,734,723 | 89,554,560 | 709,966 | 340,105 |
|
| 55 |
+
| 2026-03-13 | 7 | 68,599,649 | 68,599,649 | 68,188,511 | 55,110,528 | 411,138 | 185,043 |
|
| 56 |
+
| 2026-03-15 | 6 | 972,313 | 972,313 | 952,374 | 838,912 | 19,939 | 13,994 |
|
| 57 |
+
| 2026-03-16 | 8 | 5,367,296 | 5,367,296 | 5,288,510 | 4,711,680 | 78,786 | 38,822 |
|
| 58 |
+
| 2026-03-17 | 1 | 3,009,062 | 3,009,062 | 2,988,236 | 2,400,000 | 20,826 | 9,320 |
|
| 59 |
+
| 2026-03-19 | 6 | 5,953,315 | 5,953,315 | 5,903,652 | 5,102,208 | 49,663 | 7,583 |
|
| 60 |
+
| 2026-03-20 | 9 | 14,247,345 | 14,247,345 | 14,098,575 | 12,846,592 | 148,770 | 26,244 |
|
| 61 |
+
| 2026-03-22 | 1 | 3,317,062 | 3,317,062 | 3,305,352 | 2,819,456 | 11,710 | 2,378 |
|
| 62 |
+
| 2026-03-24 | 6 | 21,773,327 | 21,773,327 | 21,545,181 | 18,719,872 | 228,146 | 28,934 |
|
| 63 |
+
| 2026-03-25 | 2 | 15,794,732 | 15,794,732 | 15,689,027 | 14,278,272 | 105,705 | 14,028 |
|
| 64 |
+
| 2026-03-26 | 4 | 17,475,352 | 17,475,352 | 17,365,616 | 16,159,360 | 109,736 | 11,644 |
|
| 65 |
+
| 2026-03-27 | 1 | 98,877 | 98,877 | 97,169 | 71,552 | 1,708 | 604 |
|
| 66 |
+
| 2026-03-28 | 3 | 7,712,399 | 7,712,399 | 7,664,563 | 7,005,440 | 47,836 | 13,515 |
|
| 67 |
+
| 2026-03-31 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
|
| 68 |
+
| 2026-04-01 | 3 | 25,508,023 | 25,508,023 | 25,350,746 | 20,315,904 | 157,277 | 37,958 |
|
| 69 |
+
| 2026-04-02 | 4 | 17,199,934 | 17,199,934 | 17,062,790 | 14,398,848 | 137,144 | 35,101 |
|
| 70 |
+
| 2026-04-04 | 3 | 46,566,280 | 46,566,280 | 46,287,856 | 41,528,704 | 278,424 | 75,164 |
|
| 71 |
+
| 2026-04-05 | 6 | 39,855,513 | 39,855,513 | 39,651,697 | 33,805,568 | 203,816 | 50,687 |
|
| 72 |
+
| 2026-04-06 | 9 | 65,364,640 | 65,364,640 | 64,956,269 | 56,659,584 | 408,371 | 98,417 |
|
| 73 |
+
| 2026-04-08 | 7 | 28,703,787 | 28,703,787 | 28,511,836 | 23,291,904 | 191,951 | 61,081 |
|
| 74 |
+
| 2026-04-10 | 2 | 6,955,652 | 6,955,652 | 6,911,550 | 5,532,928 | 44,102 | 11,076 |
|
| 75 |
+
| 2026-04-11 | 7 | 40,151,055 | 40,151,055 | 40,010,387 | 37,590,016 | 140,668 | 44,009 |
|
| 76 |
+
| 2026-04-12 | 24 | 119,779,328 | 119,779,328 | 119,335,097 | 114,489,472 | 444,231 | 126,296 |
|
| 77 |
+
| 2026-04-13 | 2 | 44,278,404 | 44,278,404 | 44,178,204 | 41,139,200 | 100,200 | 16,762 |
|
| 78 |
+
| 2026-04-14 | 4 | 8,627,447 | 8,627,447 | 8,582,567 | 7,647,232 | 44,880 | 13,293 |
|
| 79 |
+
| 2026-04-16 | 3 | 59,357,456 | 59,357,456 | 59,092,558 | 56,559,360 | 264,898 | 125,030 |
|
| 80 |
+
| 2026-04-20 | 1 | 13,711,641 | 13,711,641 | 13,653,855 | 13,032,832 | 57,786 | 12,196 |
|
| 81 |
+
| 2026-04-21 | 115 | 300,116,344 | 300,116,344 | 298,325,385 | 276,096,768 | 1,790,959 | 610,982 |
|
| 82 |
+
| 2026-04-22 | 14 | 22,059,804 | 22,059,804 | 21,867,477 | 19,655,296 | 192,327 | 71,510 |
|
| 83 |
+
|
| 84 |
+
## Weekly Tokens
|
| 85 |
+
|
| 86 |
+
| Label | Sessions | Tokens | Rollout total | Input | Cached input | Output | Reasoning |
|
| 87 |
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
| 88 |
+
| 2026-W06 | 14 | 79,547,371 | 79,547,371 | 79,116,105 | 67,535,360 | 431,266 | 187,904 |
|
| 89 |
+
| 2026-W07 | 6 | 8,405,242 | 8,405,242 | 8,356,864 | 6,670,208 | 48,378 | 22,208 |
|
| 90 |
+
| 2026-W08 | 11 | 41,320,017 | 41,320,017 | 41,038,802 | 37,732,608 | 281,215 | 133,329 |
|
| 91 |
+
| 2026-W09 | 20 | 8,762,971 | 8,762,971 | 8,620,407 | 7,333,504 | 142,564 | 68,635 |
|
| 92 |
+
| 2026-W10 | 33 | 7,984,360 | 7,984,360 | 7,825,659 | 6,924,672 | 158,701 | 101,376 |
|
| 93 |
+
| 2026-W11 | 45 | 176,206,664 | 176,206,664 | 174,981,117 | 148,091,392 | 1,225,547 | 601,454 |
|
| 94 |
+
| 2026-W12 | 25 | 31,894,080 | 31,894,080 | 31,584,325 | 27,879,936 | 309,755 | 84,347 |
|
| 95 |
+
| 2026-W13 | 16 | 62,854,687 | 62,854,687 | 62,361,556 | 56,234,496 | 493,131 | 68,725 |
|
| 96 |
+
| 2026-W14 | 17 | 129,129,750 | 129,129,750 | 128,353,089 | 110,049,024 | 776,661 | 198,910 |
|
| 97 |
+
| 2026-W15 | 49 | 260,954,462 | 260,954,462 | 259,725,139 | 237,563,904 | 1,229,323 | 340,879 |
|
| 98 |
+
| 2026-W16 | 9 | 112,263,307 | 112,263,307 | 111,853,329 | 105,345,792 | 409,978 | 155,085 |
|
| 99 |
+
| 2026-W17 | 130 | 335,887,789 | 335,887,789 | 333,846,717 | 308,784,896 | 2,041,072 | 694,688 |
|
| 100 |
+
|
| 101 |
+
## Tokens By Cwd
|
| 102 |
+
|
| 103 |
+
| Label | Sessions | Tokens | Rollout total | Input | Cached input | Output | Reasoning |
|
| 104 |
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
| 105 |
+
| ~/Projekte/HeumandenParty | 25 | 147,920,810 | 147,920,810 | 147,263,059 | 135,344,768 | 657,751 | 224,690 |
|
| 106 |
+
| ~ | 65 | 143,305,952 | 143,305,952 | 142,271,611 | 118,259,584 | 1,034,341 | 411,954 |
|
| 107 |
+
| ~/Projekte/UEBER_AGENT | 14 | 95,265,645 | 95,265,645 | 94,690,320 | 82,054,784 | 575,325 | 136,176 |
|
| 108 |
+
| ~/Projekte/PromptBoost | 40 | 91,369,695 | 91,369,695 | 90,715,571 | 84,423,552 | 654,124 | 254,702 |
|
| 109 |
+
| ~/Projekte/Zentrale | 19 | 86,591,689 | 86,591,689 | 86,233,084 | 82,599,424 | 358,605 | 98,470 |
|
| 110 |
+
| ~/Projekte/Sidecar-V7 | 9 | 84,675,641 | 84,675,641 | 84,245,938 | 74,833,280 | 429,703 | 197,775 |
|
| 111 |
+
| ~/Projekte | 28 | 83,595,490 | 83,595,490 | 83,172,046 | 74,665,344 | 423,444 | 112,523 |
|
| 112 |
+
| ~/Dokumente/Pläne | 4 | 66,513,874 | 66,513,874 | 66,247,523 | 57,384,832 | 266,351 | 83,776 |
|
| 113 |
+
| ~/Projekte/FirstRealHarnessEvaluation_KarpathiesMD | 2 | 59,357,456 | 59,357,456 | 59,092,558 | 56,559,360 | 264,898 | 125,030 |
|
| 114 |
+
| ~/clawd | 4 | 49,462,644 | 49,462,644 | 49,155,998 | 43,810,432 | 306,646 | 91,996 |
|
| 115 |
+
| ~/DataEngeeneeringKEEPA | 6 | 46,940,456 | 46,940,456 | 46,696,473 | 41,869,440 | 243,983 | 105,385 |
|
| 116 |
+
| ~/SetUP/Monitor_my_Monitors | 3 | 37,573,267 | 37,573,267 | 37,477,005 | 36,243,584 | 96,262 | 33,239 |
|
| 117 |
+
| ~/Projekte/PromptBoost/personalPromptBoost | 13 | 22,802,481 | 22,802,481 | 22,611,147 | 20,876,160 | 191,334 | 57,401 |
|
| 118 |
+
| ~/Projekte/Jobs_Selbständigkeit_Geldverdienen/AgentTestUniSupport | 2 | 19,887,811 | 19,887,811 | 19,747,782 | 16,509,568 | 140,029 | 26,289 |
|
| 119 |
+
| ~/Projekte/PromptGarage | 1 | 19,452,133 | 19,452,133 | 19,394,544 | 18,764,544 | 57,589 | 18,018 |
|
| 120 |
+
| ~/Projekte/Sonnenuhr | 7 | 18,900,534 | 18,900,534 | 18,712,969 | 16,705,024 | 187,565 | 107,257 |
|
| 121 |
+
| ~/Projekte/PseudoLogikPyhthonCPP | 2 | 16,329,762 | 16,329,762 | 16,254,080 | 15,190,656 | 75,682 | 20,994 |
|
| 122 |
+
| ~/Projekte/Jobs_Selbständigkeit_Geldverdienen/aidvance-proposal | 2 | 15,236,493 | 15,236,493 | 15,153,630 | 14,106,752 | 82,863 | 7,162 |
|
| 123 |
+
| ~/Projekte/KomandoZentral | 1 | 10,463,900 | 10,463,900 | 10,379,137 | 9,012,224 | 84,763 | 11,443 |
|
| 124 |
+
| ~/Projekte/PortfolioTimeline | 1 | 10,249,632 | 10,249,632 | 10,174,172 | 9,088,640 | 75,460 | 10,612 |
|
| 125 |
+
| ~/.claude | 3 | 9,009,529 | 9,009,529 | 8,957,065 | 8,283,264 | 52,464 | 16,602 |
|
| 126 |
+
| ~/ProjekteV2/CodexDashboard | 2 | 8,661,587 | 8,661,587 | 8,596,572 | 7,898,368 | 65,015 | 10,400 |
|
| 127 |
+
| ~/Projekte/Sidecar-V8 | 1 | 8,647,140 | 8,647,140 | 8,563,822 | 6,135,040 | 83,318 | 36,118 |
|
| 128 |
+
| ~/Projekte/Amazon | 2 | 8,419,747 | 8,419,747 | 8,378,736 | 7,515,136 | 41,011 | 12,014 |
|
| 129 |
+
| ~/Projekte/AgentArena | 13 | 7,849,846 | 7,849,846 | 7,764,724 | 7,166,464 | 85,122 | 43,235 |
|
| 130 |
+
| ~/Codex | 3 | 7,099,187 | 7,099,187 | 7,047,299 | 6,103,680 | 51,888 | 14,249 |
|
| 131 |
+
| ~/Projekte/NasaCode/Autoresearch | 1 | 6,896,321 | 6,896,321 | 6,864,934 | 6,334,464 | 31,387 | 8,024 |
|
| 132 |
+
| ~/Projekte/MultiHarnessStudio | 6 | 6,580,156 | 6,580,156 | 6,497,175 | 4,835,584 | 82,981 | 24,300 |
|
| 133 |
+
| ~/Projekte/BahnAgent | 3 | 5,287,171 | 5,287,171 | 5,247,750 | 4,559,872 | 39,421 | 7,976 |
|
| 134 |
+
| ~/Projekte/MetaMetaMeta | 1 | 5,180,427 | 5,180,427 | 5,107,914 | 4,216,576 | 72,513 | 5,337 |
|
| 135 |
+
| ~/Projekte/ClaudeCodePanel | 21 | 5,004,177 | 5,004,177 | 4,896,768 | 4,237,568 | 107,409 | 70,091 |
|
| 136 |
+
| ~/ProjekteV2/CodexWebsiteSamuelClaudecode | 6 | 4,856,550 | 4,856,550 | 4,797,674 | 4,300,544 | 58,876 | 11,598 |
|
| 137 |
+
| ~/Projekte/Jobs_Selbständigkeit_Geldverdienen/AgentTestUniSupport/docs | 1 | 4,068,531 | 4,068,531 | 4,048,457 | 3,692,928 | 20,074 | 5,899 |
|
| 138 |
+
| ~/Projekte/Sidecar-ng | 2 | 3,778,526 | 3,778,526 | 3,753,634 | 3,067,776 | 24,892 | 10,022 |
|
| 139 |
+
| ~/Projekte/BahnAgent/HD-St.Anton | 1 | 3,588,293 | 3,588,293 | 3,566,427 | 3,453,056 | 21,866 | 9,190 |
|
| 140 |
+
| ~/Projekte/Sidecar-ng-dashboard | 1 | 3,565,535 | 3,565,535 | 3,533,244 | 3,355,264 | 32,291 | 4,937 |
|
| 141 |
+
| ~/.hermes | 2 | 3,317,062 | 3,317,062 | 3,305,352 | 2,819,456 | 11,710 | 2,378 |
|
| 142 |
+
| ~/Projekte/schloss_PDF | 1 | 3,245,804 | 3,245,804 | 3,229,768 | 3,069,824 | 16,036 | 4,866 |
|
| 143 |
+
| ~/ClaudesReich | 3 | 2,206,746 | 2,206,746 | 2,139,356 | 1,719,296 | 67,390 | 51,059 |
|
| 144 |
+
| ~/Dokumente/durchstarten | 1 | 2,177,869 | 2,177,869 | 2,165,792 | 1,844,224 | 12,077 | 3,264 |
|
| 145 |
+
| ~/Projekte/Sidecar-V7-V2 | 1 | 1,906,923 | 1,906,923 | 1,893,090 | 1,818,624 | 13,833 | 9,278 |
|
| 146 |
+
| ~/abgabe | 3 | 1,904,474 | 1,904,474 | 1,885,225 | 1,680,128 | 19,249 | 9,211 |
|
| 147 |
+
| ~/Projekte/Codex_Usage_Profil | 1 | 1,863,742 | 1,863,742 | 1,839,771 | 1,688,192 | 23,971 | 6,446 |
|
| 148 |
+
| ~/Projekte/AgentIDE | 3 | 1,595,515 | 1,595,515 | 1,563,469 | 1,397,760 | 32,046 | 22,910 |
|
| 149 |
+
| ~/Projekte/Jobs_Selbständigkeit_Geldverdienen | 1 | 1,482,737 | 1,482,737 | 1,459,527 | 1,327,488 | 23,210 | 3,945 |
|
| 150 |
+
| ~/.claude/usage | 1 | 1,205,428 | 1,205,428 | 1,179,696 | 1,085,696 | 25,732 | 8,416 |
|
| 151 |
+
| ~/DataEngeeneeringKEEPA/KeepaProjectsforDataEngeneering3BranchesMerge | 6 | 1,152,226 | 1,152,226 | 1,129,759 | 927,360 | 22,467 | 11,740 |
|
| 152 |
+
| ~/Projekte/ACPcodex | 1 | 1,059,170 | 1,059,170 | 1,043,792 | 910,848 | 15,378 | 8,018 |
|
| 153 |
+
| ~/Projekte/NasaCode | 1 | 985,209 | 985,209 | 970,106 | 897,408 | 15,103 | 1,784 |
|
| 154 |
+
| ~/Projekte/Kaggle5dayAgent | 2 | 913,047 | 913,047 | 897,573 | 686,592 | 15,474 | 5,673 |
|
| 155 |
+
| ~/ProjekteV2/CodexEval2 | 1 | 729,208 | 729,208 | 704,329 | 647,680 | 24,879 | 4,246 |
|
| 156 |
+
| ~/Meta | 1 | 718,880 | 718,880 | 707,059 | 528,512 | 11,821 | 4,379 |
|
| 157 |
+
| ~/Projekte/HarnessEcosystem | 1 | 600,507 | 600,507 | 592,621 | 502,656 | 7,886 | 1,399 |
|
| 158 |
+
| ~/Projekte/StudyAgent | 1 | 511,185 | 511,185 | 501,306 | 464,768 | 9,879 | 7,380 |
|
| 159 |
+
| ~/Projekte/ShortcutCounter | 1 | 441,229 | 441,229 | 435,073 | 398,976 | 6,156 | 3,416 |
|
| 160 |
+
| ~/Projekte/TypoTuner | 3 | 430,804 | 430,804 | 412,494 | 324,992 | 18,310 | 13,352 |
|
| 161 |
+
| ~/Projekte/SandrasWritingWorld | 3 | 347,623 | 347,623 | 340,146 | 290,560 | 7,477 | 4,607 |
|
| 162 |
+
| ~/CodexReich | 2 | 282,250 | 282,250 | 271,237 | 254,208 | 11,013 | 8,192 |
|
| 163 |
+
| ~/Projekte/Sidecar | 1 | 251,167 | 251,167 | 245,022 | 213,504 | 6,145 | 4,675 |
|
| 164 |
+
| ~/Projekte/PromptEngeneering | 2 | 207,700 | 207,700 | 203,831 | 132,096 | 3,869 | 1,279 |
|
| 165 |
+
| ~/ClaudesReich/SessionBrowser | 2 | 203,849 | 203,849 | 196,188 | 170,880 | 7,661 | 5,165 |
|
| 166 |
+
| ~/Projekte/Sidecar-V7-Lite | 1 | 197,279 | 197,279 | 190,627 | 177,792 | 6,652 | 4,599 |
|
| 167 |
+
| ~/Projekte/FireTracker | 2 | 191,892 | 191,892 | 184,419 | 153,344 | 7,473 | 5,715 |
|
| 168 |
+
| ~/Bilder/Anzug/Logo | 1 | 141,042 | 141,042 | 138,537 | 102,016 | 2,505 | 1,280 |
|
| 169 |
+
| ~/DataEngeeneeringKEEPA/VomProfPDF | 1 | 135,655 | 135,655 | 131,074 | 119,168 | 4,581 | 2,463 |
|
| 170 |
+
| ~/Orderformyaistuff | 1 | 132,215 | 132,215 | 131,214 | 112,128 | 1,001 | 64 |
|
| 171 |
+
| ~/OrdnungvonGedanken/git | 1 | 113,347 | 113,347 | 108,699 | 96,384 | 4,648 | 1,633 |
|
| 172 |
+
| ~/ClaudesReich/Visualisierung | 3 | 86,970 | 86,970 | 85,224 | 67,584 | 1,746 | 493 |
|
| 173 |
+
| ~/Projekte/MyAIGame | 2 | 72,823 | 72,823 | 62,967 | 51,328 | 9,856 | 6,964 |
|
| 174 |
+
| /tmp/MyAIGame | 1 | 11,035 | 11,035 | 7,924 | 6,784 | 3,111 | 2,367 |
|
| 175 |
+
| ~/SetUP | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
|
| 176 |
+
| ~/Projekte/HarnessEcosystem/sidebyside | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
|
| 177 |
+
|
| 178 |
+
## Tokens By Model
|
| 179 |
+
|
| 180 |
+
| Label | Sessions | Tokens | Rollout total | Input | Cached input | Output | Reasoning |
|
| 181 |
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
| 182 |
+
| gpt-5.4 | 190 | 1,002,621,471 | 1,002,621,471 | 997,085,786 | 895,809,024 | 5,535,685 | 1,652,172 |
|
| 183 |
+
| gpt-5.4-mini | 64 | 94,242,789 | 94,242,789 | 93,515,945 | 87,385,344 | 726,844 | 349,506 |
|
| 184 |
+
| gpt-5.1-codex-max | 14 | 86,258,755 | 86,258,755 | 85,848,562 | 72,738,816 | 410,193 | 157,571 |
|
| 185 |
+
| gpt-5.3-codex | 97 | 63,196,733 | 63,196,733 | 62,443,450 | 56,599,040 | 753,283 | 432,430 |
|
| 186 |
+
| gpt-5.1-codex-mini | 2 | 4,583,943 | 4,583,943 | 4,546,444 | 4,075,904 | 37,499 | 7,045 |
|
| 187 |
+
| gpt-5.2-codex | 5 | 4,307,009 | 4,307,009 | 4,222,922 | 3,537,664 | 84,087 | 58,816 |
|
| 188 |
+
| unknown | 3 | 0 | 0 | 0 | 0 | 0 | 0 |
|
| 189 |
+
|
| 190 |
+
## Tokens By Role
|
| 191 |
+
|
| 192 |
+
| Label | Sessions | Tokens | Rollout total | Input | Cached input | Output | Reasoning |
|
| 193 |
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
| 194 |
+
| main | 240 | 1,162,370,493 | 1,162,370,493 | 1,155,950,486 | 1,039,647,488 | 6,420,007 | 2,223,740 |
|
| 195 |
+
| unknown | 17 | 31,239,166 | 31,239,166 | 30,924,883 | 27,394,176 | 314,283 | 116,098 |
|
| 196 |
+
| worker | 18 | 30,777,412 | 30,777,412 | 30,458,569 | 28,003,584 | 318,843 | 108,953 |
|
| 197 |
+
| explorer | 94 | 30,734,460 | 30,734,460 | 30,240,125 | 25,049,600 | 494,335 | 208,680 |
|
| 198 |
+
| default | 6 | 89,169 | 89,169 | 89,046 | 50,944 | 123 | 69 |
|
| 199 |
+
|
| 200 |
+
## Main Vs Subagent
|
| 201 |
+
|
| 202 |
+
| Label | Sessions | Tokens | Rollout total | Input | Cached input | Output | Reasoning |
|
| 203 |
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
| 204 |
+
| main | 250 | 1,170,627,399 | 1,170,627,399 | 1,164,127,535 | 1,046,924,928 | 6,499,864 | 2,236,967 |
|
| 205 |
+
| subagent | 125 | 84,583,301 | 84,583,301 | 83,535,574 | 73,220,864 | 1,047,727 | 420,573 |
|
| 206 |
+
|
| 207 |
+
## Top Sessions
|
| 208 |
+
|
| 209 |
+
| Created | Tokens | Kind | Model | Role | Cwd | Session | Rollout |
|
| 210 |
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
| 211 |
+
| 2026-04-16 13:01 | 47,959,797 | main | gpt-5.4-mini | main | ~/Projekte/FirstRealHarnessEvaluation_KarpathiesMD | 019d95f4-0198-7e10-9c95-ecd79e771e27 | /home/smlflg/.codex/sessions/2026/04/16/rollout-2026-04-16T13-01-29-019d95f4-0198-7e10-9c95-ecd79e771e27.jsonl |
|
| 212 |
+
| 2026-04-04 16:27 | 45,688,987 | main | gpt-5.4 | main | ~/clawd | 019d58e4-046a-7c10-a832-f8c706647456 | /home/smlflg/.codex/sessions/2026/04/04/rollout-2026-04-04T16-27-11-019d58e4-046a-7c10-a832-f8c706647456.jsonl |
|
| 213 |
+
| 2026-04-13 07:09 | 43,897,402 | main | gpt-5.4 | main | ~/Projekte/HeumandenParty | 019d853e-b868-7053-bb8c-630df03c6eea | /home/smlflg/.codex/sessions/2026/04/13/rollout-2026-04-13T07-09-33-019d853e-b868-7053-bb8c-630df03c6eea.jsonl |
|
| 214 |
+
| 2026-03-13 12:03 | 42,283,906 | main | gpt-5.4 | main | ~/Projekte/Sidecar-V7 | 019ce6dd-5a1c-7fe3-a300-b98983ae4bb8 | /home/smlflg/.codex/sessions/2026/03/13/rollout-2026-03-13T12-03-12-019ce6dd-5a1c-7fe3-a300-b98983ae4bb8.jsonl |
|
| 215 |
+
| 2026-02-05 12:11 | 40,984,928 | main | gpt-5.1-codex-max | main | ~/Dokumente/Pläne | 019c2d80-2f19-7521-9c87-4d6be1ffc9f1 | /home/smlflg/.codex/sessions/2026/02/05/rollout-2026-02-05T12-11-41-019c2d80-2f19-7521-9c87-4d6be1ffc9f1.jsonl |
|
| 216 |
+
| 2026-03-12 00:59 | 34,165,684 | main | gpt-5.4 | main | ~ | 019cdf57-c2c6-7a92-9096-6dac18fc5177 | /home/smlflg/.codex/sessions/2026/03/12/rollout-2026-03-12T00-59-56-019cdf57-c2c6-7a92-9096-6dac18fc5177.jsonl |
|
| 217 |
+
| 2026-02-18 17:07 | 32,848,911 | main | gpt-5.3-codex | main | ~/DataEngeeneeringKEEPA | 019c7181-a37e-7ae2-8870-c4c16655ec52 | /home/smlflg/.codex/sessions/2026/02/18/rollout-2026-02-18T17-07-27-019c7181-a37e-7ae2-8870-c4c16655ec52.jsonl |
|
| 218 |
+
| 2026-04-21 23:03 | 32,619,865 | main | gpt-5.4 | main | ~/Projekte/HeumandenParty | 019db1db-150f-7662-b607-30871c33af75 | /home/smlflg/.codex/sessions/2026/04/21/rollout-2026-04-21T23-03-38-019db1db-150f-7662-b607-30871c33af75.jsonl |
|
| 219 |
+
| 2026-04-05 18:49 | 29,145,038 | main | gpt-5.4 | main | ~/Projekte/UEBER_AGENT | 019d5e8c-39f3-7db1-a48b-d4eb2b50298e | /home/smlflg/.codex/sessions/2026/04/05/rollout-2026-04-05T18-49-01-019d5e8c-39f3-7db1-a48b-d4eb2b50298e.jsonl |
|
| 220 |
+
| 2026-04-06 12:58 | 25,127,211 | main | gpt-5.4 | main | ~/Projekte/UEBER_AGENT | 019d6271-60b8-7621-a2c4-7a66afca9f80 | /home/smlflg/.codex/sessions/2026/04/06/rollout-2026-04-06T12-58-10-019d6271-60b8-7621-a2c4-7a66afca9f80.jsonl |
|
| 221 |
+
| 2026-02-07 19:08 | 22,356,063 | main | gpt-5.1-codex-max | main | ~/Dokumente/Pläne | 019c394a-8761-7823-8f7e-7457d21d79af | /home/smlflg/.codex/sessions/2026/02/07/rollout-2026-02-07T19-08-31-019c394a-8761-7823-8f7e-7457d21d79af.jsonl |
|
| 222 |
+
| 2026-04-08 10:23 | 22,123,631 | main | gpt-5.4 | main | ~/Projekte/HeumandenParty | 019d6c30-e1c5-7441-9ed6-afc8f2bc9861 | /home/smlflg/.codex/sessions/2026/04/08/rollout-2026-04-08T10-23-56-019d6c30-e1c5-7441-9ed6-afc8f2bc9861.jsonl |
|
| 223 |
+
| 2026-04-21 23:28 | 21,430,259 | main | gpt-5.4 | main | ~/Projekte/HeumandenParty | 019db1f1-e994-75c0-94d8-6edc93203dd7 | /home/smlflg/.codex/sessions/2026/04/21/rollout-2026-04-21T23-28-34-019db1f1-e994-75c0-94d8-6edc93203dd7.jsonl |
|
| 224 |
+
| 2026-04-21 15:43 | 21,410,253 | main | gpt-5.4 | main | ~ | 019db048-0123-7242-89b9-d6083591212b | /home/smlflg/.codex/sessions/2026/04/21/rollout-2026-04-21T15-43-22-019db048-0123-7242-89b9-d6083591212b.jsonl |
|
| 225 |
+
| 2026-04-21 15:31 | 21,194,654 | main | gpt-5.4 | main | ~/Projekte/PromptBoost | 019db03d-1f96-7592-8fef-1f10125ebe0c | /home/smlflg/.codex/sessions/2026/04/21/rollout-2026-04-21T15-31-29-019db03d-1f96-7592-8fef-1f10125ebe0c.jsonl |
|
| 226 |
+
| 2026-03-12 15:10 | 21,018,788 | main | gpt-5.4 | main | ~/Projekte/Sidecar-V7 | 019ce262-7359-7ae2-b3c1-e1c5d1a63e66 | /home/smlflg/.codex/sessions/2026/03/12/rollout-2026-03-12T15-10-28-019ce262-7359-7ae2-b3c1-e1c5d1a63e66.jsonl |
|
| 227 |
+
| 2026-04-21 15:27 | 20,456,527 | main | gpt-5.4 | main | ~/Projekte/PromptBoost | 019db039-1b8f-7370-bab6-9e25fd16e912 | /home/smlflg/.codex/sessions/2026/04/21/rollout-2026-04-21T15-27-05-019db039-1b8f-7370-bab6-9e25fd16e912.jsonl |
|
| 228 |
+
| 2026-04-12 15:58 | 20,372,968 | main | gpt-5.4 | main | ~/Projekte/Zentrale | 019d81fc-7347-7523-b30f-4d3ddce562e1 | /home/smlflg/.codex/sessions/2026/04/12/rollout-2026-04-12T15-58-18-019d81fc-7347-7523-b30f-4d3ddce562e1.jsonl |
|
| 229 |
+
| 2026-03-12 15:14 | 19,745,610 | main | gpt-5.4 | main | ~/Projekte/Sidecar-V7 | 019ce266-3a71-79e2-ada1-226867a34de3 | /home/smlflg/.codex/sessions/2026/03/12/rollout-2026-03-12T15-14-36-019ce266-3a71-79e2-ada1-226867a34de3.jsonl |
|
| 230 |
+
| 2026-04-21 14:53 | 19,452,133 | main | gpt-5.4 | main | ~/Projekte/PromptGarage | 019db01a-8e1c-7560-b78f-63857f297f47 | /home/smlflg/.codex/sessions/2026/04/21/rollout-2026-04-21T14-53-43-019db01a-8e1c-7560-b78f-63857f297f47.jsonl |
|
| 231 |
+
|
| 232 |
+
## Data Warnings
|
| 233 |
+
|
| 234 |
+
- `Malformed JSONL lines in /home/smlflg/.codex/sessions/2026/04/21/rollout-2026-04-21T18-15-04-019db0d2-e62b-78b3-b8f3-e0c70af3aa6c.jsonl: 1`
|
tests/test_profiler.py
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
import json
|
| 4 |
+
import sqlite3
|
| 5 |
+
import tempfile
|
| 6 |
+
import unittest
|
| 7 |
+
from datetime import datetime
|
| 8 |
+
from pathlib import Path
|
| 9 |
+
from zoneinfo import ZoneInfo
|
| 10 |
+
|
| 11 |
+
from codex_usage_profiler.core import build_report
|
| 12 |
+
from codex_usage_profiler.render import render_html, render_markdown
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
class UsageProfilerTests(unittest.TestCase):
|
| 16 |
+
def test_aggregates_threads_edges_and_rollout_breakdowns(self) -> None:
|
| 17 |
+
with tempfile.TemporaryDirectory() as tmp:
|
| 18 |
+
root = Path(tmp)
|
| 19 |
+
state = root / "state_5.sqlite"
|
| 20 |
+
sessions_dir = root / "sessions"
|
| 21 |
+
sessions_dir.mkdir()
|
| 22 |
+
main_rollout = sessions_dir / "rollout-main.jsonl"
|
| 23 |
+
child_rollout = sessions_dir / "rollout-child.jsonl"
|
| 24 |
+
|
| 25 |
+
_write_rollout(
|
| 26 |
+
main_rollout,
|
| 27 |
+
[
|
| 28 |
+
{"type": "turn_context", "payload": {"model": "gpt-5.4", "cwd": "/home/test/project"}},
|
| 29 |
+
{"type": "event_msg", "payload": {"type": "task_started"}},
|
| 30 |
+
{
|
| 31 |
+
"type": "event_msg",
|
| 32 |
+
"payload": {
|
| 33 |
+
"type": "token_count",
|
| 34 |
+
"info": {
|
| 35 |
+
"total_token_usage": {
|
| 36 |
+
"input_tokens": 70,
|
| 37 |
+
"cached_input_tokens": 20,
|
| 38 |
+
"output_tokens": 25,
|
| 39 |
+
"reasoning_output_tokens": 5,
|
| 40 |
+
"total_tokens": 100,
|
| 41 |
+
}
|
| 42 |
+
},
|
| 43 |
+
},
|
| 44 |
+
},
|
| 45 |
+
],
|
| 46 |
+
malformed=True,
|
| 47 |
+
)
|
| 48 |
+
_write_rollout(
|
| 49 |
+
child_rollout,
|
| 50 |
+
[
|
| 51 |
+
{"type": "turn_context", "payload": {"model": "gpt-5.4-mini", "cwd": "/home/test/project"}},
|
| 52 |
+
{
|
| 53 |
+
"type": "event_msg",
|
| 54 |
+
"payload": {
|
| 55 |
+
"type": "token_count",
|
| 56 |
+
"info": {
|
| 57 |
+
"total_token_usage": {
|
| 58 |
+
"input_tokens": 35,
|
| 59 |
+
"cached_input_tokens": 10,
|
| 60 |
+
"output_tokens": 12,
|
| 61 |
+
"reasoning_output_tokens": 3,
|
| 62 |
+
"total_tokens": 50,
|
| 63 |
+
}
|
| 64 |
+
},
|
| 65 |
+
},
|
| 66 |
+
},
|
| 67 |
+
],
|
| 68 |
+
)
|
| 69 |
+
_create_state(
|
| 70 |
+
state,
|
| 71 |
+
[
|
| 72 |
+
{
|
| 73 |
+
"id": "main",
|
| 74 |
+
"rollout_path": str(main_rollout),
|
| 75 |
+
"created_at_ms": _epoch_ms("2026-04-20T22:30:00+00:00"),
|
| 76 |
+
"updated_at_ms": _epoch_ms("2026-04-20T23:00:00+00:00"),
|
| 77 |
+
"model_provider": "openai",
|
| 78 |
+
"cwd": "/home/test/project",
|
| 79 |
+
"title": "Main work",
|
| 80 |
+
"tokens_used": 100,
|
| 81 |
+
"agent_nickname": "",
|
| 82 |
+
"agent_role": "",
|
| 83 |
+
"model": None,
|
| 84 |
+
},
|
| 85 |
+
{
|
| 86 |
+
"id": "child",
|
| 87 |
+
"rollout_path": str(child_rollout),
|
| 88 |
+
"created_at_ms": _epoch_ms("2026-04-21T10:00:00+00:00"),
|
| 89 |
+
"updated_at_ms": _epoch_ms("2026-04-21T10:05:00+00:00"),
|
| 90 |
+
"model_provider": "openai",
|
| 91 |
+
"cwd": "/home/test/project",
|
| 92 |
+
"title": "Explore",
|
| 93 |
+
"tokens_used": 50,
|
| 94 |
+
"agent_nickname": "Noether",
|
| 95 |
+
"agent_role": "explorer",
|
| 96 |
+
"model": "gpt-5.4-mini",
|
| 97 |
+
},
|
| 98 |
+
],
|
| 99 |
+
[("main", "child")],
|
| 100 |
+
)
|
| 101 |
+
|
| 102 |
+
report = build_report(
|
| 103 |
+
state_path=state,
|
| 104 |
+
sessions_dir=sessions_dir,
|
| 105 |
+
tz_name="Europe/Berlin",
|
| 106 |
+
now=datetime(2026, 4, 22, 12, tzinfo=ZoneInfo("Europe/Berlin")),
|
| 107 |
+
)
|
| 108 |
+
|
| 109 |
+
self.assertEqual(report.total_tokens, 150)
|
| 110 |
+
self.assertEqual(report.daily[0].label, "2026-04-21")
|
| 111 |
+
self.assertEqual(report.daily[0].tokens, 150)
|
| 112 |
+
self.assertEqual(report.weekly[0].label, "2026-W17")
|
| 113 |
+
self.assertEqual({bucket.label: bucket.tokens for bucket in report.by_kind}, {"main": 100, "subagent": 50})
|
| 114 |
+
self.assertEqual({bucket.label: bucket.tokens for bucket in report.by_role}, {"main": 100, "explorer": 50})
|
| 115 |
+
self.assertEqual({bucket.label: bucket.tokens for bucket in report.by_model}, {"gpt-5.4": 100, "gpt-5.4-mini": 50})
|
| 116 |
+
self.assertEqual(report.rollout_totals.total_tokens, 150)
|
| 117 |
+
self.assertEqual(report.rollout_totals.cached_input_tokens, 30)
|
| 118 |
+
self.assertEqual(len(report.warnings), 1)
|
| 119 |
+
|
| 120 |
+
def test_days_filter_uses_local_calendar_days(self) -> None:
|
| 121 |
+
with tempfile.TemporaryDirectory() as tmp:
|
| 122 |
+
root = Path(tmp)
|
| 123 |
+
state = root / "state_5.sqlite"
|
| 124 |
+
sessions_dir = root / "sessions"
|
| 125 |
+
sessions_dir.mkdir()
|
| 126 |
+
_create_state(
|
| 127 |
+
state,
|
| 128 |
+
[
|
| 129 |
+
{
|
| 130 |
+
"id": "old",
|
| 131 |
+
"rollout_path": "",
|
| 132 |
+
"created_at_ms": _epoch_ms("2026-04-18T12:00:00+00:00"),
|
| 133 |
+
"updated_at_ms": _epoch_ms("2026-04-18T12:00:00+00:00"),
|
| 134 |
+
"model_provider": "openai",
|
| 135 |
+
"cwd": "/tmp/a",
|
| 136 |
+
"title": "Old",
|
| 137 |
+
"tokens_used": 99,
|
| 138 |
+
"agent_nickname": "",
|
| 139 |
+
"agent_role": "",
|
| 140 |
+
"model": "gpt-5.4",
|
| 141 |
+
},
|
| 142 |
+
{
|
| 143 |
+
"id": "new",
|
| 144 |
+
"rollout_path": "",
|
| 145 |
+
"created_at_ms": _epoch_ms("2026-04-21T12:00:00+00:00"),
|
| 146 |
+
"updated_at_ms": _epoch_ms("2026-04-21T12:00:00+00:00"),
|
| 147 |
+
"model_provider": "openai",
|
| 148 |
+
"cwd": "/tmp/a",
|
| 149 |
+
"title": "New",
|
| 150 |
+
"tokens_used": 10,
|
| 151 |
+
"agent_nickname": "",
|
| 152 |
+
"agent_role": "",
|
| 153 |
+
"model": "gpt-5.4",
|
| 154 |
+
},
|
| 155 |
+
],
|
| 156 |
+
[],
|
| 157 |
+
)
|
| 158 |
+
|
| 159 |
+
report = build_report(
|
| 160 |
+
state_path=state,
|
| 161 |
+
sessions_dir=sessions_dir,
|
| 162 |
+
tz_name="Europe/Berlin",
|
| 163 |
+
days=2,
|
| 164 |
+
now=datetime(2026, 4, 22, 12, tzinfo=ZoneInfo("Europe/Berlin")),
|
| 165 |
+
)
|
| 166 |
+
|
| 167 |
+
self.assertEqual(len(report.sessions), 1)
|
| 168 |
+
self.assertEqual(report.sessions[0].thread_id, "new")
|
| 169 |
+
self.assertEqual(report.total_tokens, 10)
|
| 170 |
+
|
| 171 |
+
def test_renderers_include_expected_sections_and_escape_html(self) -> None:
|
| 172 |
+
with tempfile.TemporaryDirectory() as tmp:
|
| 173 |
+
root = Path(tmp)
|
| 174 |
+
state = root / "state_5.sqlite"
|
| 175 |
+
sessions_dir = root / "sessions"
|
| 176 |
+
sessions_dir.mkdir()
|
| 177 |
+
_create_state(
|
| 178 |
+
state,
|
| 179 |
+
[
|
| 180 |
+
{
|
| 181 |
+
"id": "s1",
|
| 182 |
+
"rollout_path": "",
|
| 183 |
+
"created_at_ms": _epoch_ms("2026-04-21T12:00:00+00:00"),
|
| 184 |
+
"updated_at_ms": _epoch_ms("2026-04-21T12:00:00+00:00"),
|
| 185 |
+
"model_provider": "openai",
|
| 186 |
+
"cwd": "/tmp/a",
|
| 187 |
+
"title": "<unsafe>",
|
| 188 |
+
"tokens_used": 10,
|
| 189 |
+
"agent_nickname": "",
|
| 190 |
+
"agent_role": "",
|
| 191 |
+
"model": "gpt-5.4",
|
| 192 |
+
}
|
| 193 |
+
],
|
| 194 |
+
[],
|
| 195 |
+
)
|
| 196 |
+
report = build_report(
|
| 197 |
+
state_path=state,
|
| 198 |
+
sessions_dir=sessions_dir,
|
| 199 |
+
tz_name="Europe/Berlin",
|
| 200 |
+
now=datetime(2026, 4, 22, 12, tzinfo=ZoneInfo("Europe/Berlin")),
|
| 201 |
+
)
|
| 202 |
+
|
| 203 |
+
markdown = render_markdown(report)
|
| 204 |
+
html = render_html(report)
|
| 205 |
+
self.assertIn("## Daily Tokens", markdown)
|
| 206 |
+
self.assertIn("## Top Sessions", markdown)
|
| 207 |
+
self.assertNotIn("<unsafe>", html)
|
| 208 |
+
self.assertNotIn("<unsafe>", html)
|
| 209 |
+
|
| 210 |
+
|
| 211 |
+
def _create_state(state: Path, rows: list[dict[str, object]], edges: list[tuple[str, str]]) -> None:
|
| 212 |
+
with sqlite3.connect(state) as conn:
|
| 213 |
+
conn.execute(
|
| 214 |
+
"""
|
| 215 |
+
CREATE TABLE threads (
|
| 216 |
+
id TEXT PRIMARY KEY,
|
| 217 |
+
rollout_path TEXT NOT NULL,
|
| 218 |
+
created_at INTEGER NOT NULL,
|
| 219 |
+
updated_at INTEGER NOT NULL,
|
| 220 |
+
created_at_ms INTEGER,
|
| 221 |
+
updated_at_ms INTEGER,
|
| 222 |
+
model_provider TEXT NOT NULL,
|
| 223 |
+
cwd TEXT NOT NULL,
|
| 224 |
+
title TEXT NOT NULL,
|
| 225 |
+
tokens_used INTEGER NOT NULL,
|
| 226 |
+
agent_nickname TEXT,
|
| 227 |
+
agent_role TEXT,
|
| 228 |
+
model TEXT
|
| 229 |
+
)
|
| 230 |
+
"""
|
| 231 |
+
)
|
| 232 |
+
conn.execute(
|
| 233 |
+
"""
|
| 234 |
+
CREATE TABLE thread_spawn_edges (
|
| 235 |
+
parent_thread_id TEXT NOT NULL,
|
| 236 |
+
child_thread_id TEXT NOT NULL PRIMARY KEY
|
| 237 |
+
)
|
| 238 |
+
"""
|
| 239 |
+
)
|
| 240 |
+
for row in rows:
|
| 241 |
+
conn.execute(
|
| 242 |
+
"""
|
| 243 |
+
INSERT INTO threads (
|
| 244 |
+
id,
|
| 245 |
+
rollout_path,
|
| 246 |
+
created_at,
|
| 247 |
+
updated_at,
|
| 248 |
+
created_at_ms,
|
| 249 |
+
updated_at_ms,
|
| 250 |
+
model_provider,
|
| 251 |
+
cwd,
|
| 252 |
+
title,
|
| 253 |
+
tokens_used,
|
| 254 |
+
agent_nickname,
|
| 255 |
+
agent_role,
|
| 256 |
+
model
|
| 257 |
+
)
|
| 258 |
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
| 259 |
+
""",
|
| 260 |
+
(
|
| 261 |
+
row["id"],
|
| 262 |
+
row["rollout_path"],
|
| 263 |
+
int(row["created_at_ms"]) // 1000,
|
| 264 |
+
int(row["updated_at_ms"]) // 1000,
|
| 265 |
+
row["created_at_ms"],
|
| 266 |
+
row["updated_at_ms"],
|
| 267 |
+
row["model_provider"],
|
| 268 |
+
row["cwd"],
|
| 269 |
+
row["title"],
|
| 270 |
+
row["tokens_used"],
|
| 271 |
+
row["agent_nickname"],
|
| 272 |
+
row["agent_role"],
|
| 273 |
+
row["model"],
|
| 274 |
+
),
|
| 275 |
+
)
|
| 276 |
+
for parent, child in edges:
|
| 277 |
+
conn.execute(
|
| 278 |
+
"INSERT INTO thread_spawn_edges (parent_thread_id, child_thread_id) VALUES (?, ?)",
|
| 279 |
+
(parent, child),
|
| 280 |
+
)
|
| 281 |
+
|
| 282 |
+
|
| 283 |
+
def _write_rollout(path: Path, events: list[dict[str, object]], malformed: bool = False) -> None:
|
| 284 |
+
with path.open("w", encoding="utf-8") as handle:
|
| 285 |
+
for event in events:
|
| 286 |
+
handle.write(json.dumps(event) + "\n")
|
| 287 |
+
if malformed:
|
| 288 |
+
handle.write("{not-json\n")
|
| 289 |
+
|
| 290 |
+
|
| 291 |
+
def _epoch_ms(value: str) -> int:
|
| 292 |
+
return int(datetime.fromisoformat(value).timestamp() * 1000)
|
| 293 |
+
|
| 294 |
+
|
| 295 |
+
if __name__ == "__main__":
|
| 296 |
+
unittest.main()
|