Skip to content

escotilha/rot-cli

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ROT — Return on Tokens

CI

Measure the economic value your AI coding work creates per dollar of compute — from real session telemetry, not vibes.

        Economic Value Created
ROT  =  ────────────────────────
        Total AI Deployment Cost

ROT instruments your Claude Code sessions and reports how much engineering time the AI gave back, priced against what it cost. It is built around one discipline: it never invents the value. It separates what it can measure from session logs from what you have to supply yourself, and labels each.

Two numbers, never conflated

Metric What it captures Source
Token/Time ROT Recovered engineering time ÷ compute cost Measured from session logs
Full-business ROT Adds cost savings, revenue, risk reduction Business inputs you supply — flagged as assumptions

The numerator term ROT can ground is time: active session time × a per-task "how long would this take me solo" multiplier × your $/hr. The business-outcome terms live in no log, so they're solicited via flags, never fabricated.

Example ROT report (synthetic demo data)

Install

Requires Python 3.9+ and jq (the jq is only used by the session hook). No dependencies beyond the standard library.

# as a CLI, straight from GitHub
pipx install git+https://github.com/escotilha/rot-cli
# or: uv tool install git+https://github.com/escotilha/rot-cli

# or from a clone (editable)
git clone https://github.com/escotilha/rot-cli.git
cd rot-cli && pip install -e .

Wire the collector into your Claude Code settings.json so every session is logged automatically:

{
  "hooks": {
    "SessionEnd": [
      { "hooks": [{ "type": "command", "command": "/abs/path/to/rot-cli/rot/hook-collect.sh" }] }
    ]
  }
}

That's the whole install — the hook appends one row per session to ~/.rot/ledger.jsonl (override with ROT_LEDGER). Installed via pipx/uv with no clone on disk? The hook script ships inside the package — rot doctor prints its absolute path. Verify everything with:

rot doctor    # hook wired? ledger growing? all models covered by the rate table?

Try it now (synthetic demo)

No session history yet? Seed a fake ledger and run a report:

ROT_LEDGER=/tmp/demo.jsonl rot demo
ROT_LEDGER=/tmp/demo.jsonl rot report --since 90d

(All demo numbers are fabricated for illustration — see examples/.)

Use it

# Seed from your existing Claude Code transcripts (one-time)
rot backfill

# Standard report
rot report --since 30d

# Scope to a project / get JSON
rot report --since 30d --project web-app --json

# REAL CASH: if you're on a flat plan, price against the actual fee
rot report --since 30d --flat-cost 200 --months 1

# Fold in substantiated business outcomes (Full-business ROT)
rot report --since 30d --cost-savings 40000 --risk-reduction 15000

# Render a shareable HTML report
rot report --since 90d --json | rot html --out /tmp/rot.html

# Annualized projection (clearly labeled as projection)
rot report --since 30d --flat-cost 200 --months 1 --json | rot annualize

# Professional one-pager — asks for your rate/plan/business inputs, then
# renders a print-ready page (Enter accepts defaults; --no-input to script it)
rot onepager

Every subcommand is also directly runnable without installing (python3 rot/rot_report.py --since 30d, ./rot/backfill.sh).

How it stays honest

  • Subagent tokens count. Agent-tool and workflow fan-outs write their transcripts to subagents/ next to the main session file — often the majority of a session's spend. The collector folds them into the session's cost, so heavy agentic work can't fly under the denominator.
  • Active time, not calendar time. Idle gaps between turns are capped (default 30 min, max_idle_gap_seconds), so a session left open overnight doesn't claim hours it didn't work. Subagent activity never extends active time — they run in parallel with you.
  • Grounded denominator. Compute cost = actual token counts × public API rates (longest-prefix matched, so dated model IDs price correctly; unknown models price at the top tier, which under-states ROT). On a flat plan, --flat-cost swaps in the real subscription fee instead.
  • Every assumption is in rot/rot_config.json and printed in every report — $/hr, the per-task counterfactual multipliers, and the task-classifier patterns. Tune them to your reality; the defaults are deliberately conservative.
  • Projection ≠ measurement. The annualizer extrapolates one measured window forward and says so on every line.

Privacy

The ledger stores no prompt text and no code. Task classification reads your prompts in memory, but what lands on disk per session is only: token counts by model, timestamps, a task-type label, the working directory, skill names, and turn counts. Safe to keep, safe to share in a report.

What's measured vs. assumed

Measured: tokens per model (main session + subagents), active session time, task type (keyword-classified from your prompts, with harness-injected markup stripped), project. Assumed (and labeled): your $/hr, the counterfactual multipliers, and any business-outcome dollars you pass in. The tool's whole value is keeping that line bright.

Configuration

Edit rot/rot_config.json (or point ROT_CONFIG elsewhere). The two levers that move the number most:

  1. hourly_rate_usd — your loaded $/hr.
  2. task_counterfactual_multiplier — per task type, how many solo hours the work would take as a multiple of measured AI active time.

Also tunable: max_idle_gap_seconds (idle threshold), task_patterns (the classifier's [label, regex] pairs — tune to your own work mix), and api_rates_per_mtok (update when pricing changes). Group directories into named projects with ROT_PROJECT_MAP='{"api":"Backend","web":"Frontend"}'.

Known caveats

  • Forked sessions double-count. /branch (fork-session) copies the full history — with its original usage — into a new session ID, so both files backfill as separate sessions. Rare in practice; if you fork a lot, prune the copies from the ledger.
  • Classification is heuristic. Keyword matching over your prompts, majority-wins. Re-running rot backfill after upgrading (or after tuning task_patterns) reclassifies sessions in place, which shifts the per-task counterfactual multipliers — so time-value figures can change versus older reports. Token counts and compute cost never depend on classification.

License

MIT — see LICENSE.

About

Return on Tokens — measure the economic value of AI coding work per dollar of compute, from Claude Code session telemetry

Topics

Resources

License

Stars

2 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors