Skip to content

Releases: kelesmert/turnlens

v0.4.0

Choose a tag to compare

@kelesmert kelesmert released this 12 Aug 18:34

See what a project cost, and count every model that contributed to a turn.

Added

  • report project, a report grouped by the directory the agent ran in. Each
    project heads a block carrying its total, with its sessions beneath it. This is
    the split your client already shows as folders, and the report could not make
    it.

    turnlens report project                    every project
    turnlens report project turnlens           that project's sessions
    turnlens report project turnlens daily     that project, day by day
    

    A name matches a project whole, so turnlens does not also mean
    turnlens-docs. A session belongs to the project it started in, so one that
    changed directory part way through is not split across two headings.

    The rows under a project are still sessions. The project is a fifth grouping
    word, not a new unit for the report.

Fixed

  • Advisor usage is no longer omitted from a turn. When Claude Code records
    an advisor_message, TurnLens keeps its model and usage separate, prices each
    model at its own rate, and adds both to the turn. A measured Sonnet turn with
    an Opus advisor moves from 733,887 tokens and $0.3641 to 799,234 tokens and
    $0.7619.

    The reason this is worth its own entry is the shape of the gap: in a second
    measured turn the advisor was 34 percent of the tokens and 64 percent of the
    cost, because an advisor's input is uncached and its model is the dearer one.
    A turn that used one was not slightly wrong.

    The live table still names the model that produced the answer. Reports and the
    exit summary name every model the turn used.

  • An agent named after report now says so. turnlens report claude
    answered Unknown grouping: claude, which is true and useless: you know
    claude is an agent, which is why you typed it. It now names the word order
    and shows the command that works.

  • Two agents in watch mode no longer get called a grouping. turnlens claude codex claimed codex needed the word report in front of it. Watching
    follows one session, so it takes one agent, and the answer for two is a report.

CSV schema change

pricing_components_json is appended as the final column. It is empty for an
ordinary single-model turn and explains every model, token category, cost status
and pricing version in a mixed turn. No existing column moved.

TurnLens refuses an existing 0.3.x CSV rather than silently interpreting it
under the new schema. Either append ,pricing_components_json to the end of its
header row or move the file and let TurnLens create a new one. Existing rows need
no other change, and reports are unaffected because they never open CSV files.

Unchanged

No command-line flag changed. Existing report JSON fields keep their meanings;
the project grouping only adds its optional project field. Single-model turns
produce the same tokens, costs, live-table model and empty component-detail cell
they would have produced under the new header before this fix.


Full diff: v0.3.2...v0.4.0

v0.3.2

Choose a tag to compare

@kelesmert kelesmert released this 09 Aug 18:29

Added

  • --last, a window that ends today. turnlens report --last 7d covers today and the six days before it. Days and weeks: 7d, 2w. Today is the first day counted, so the number you type is the number of days you get.

    Months and years are refused rather than guessed at, because their length is not fixed. Name the two dates for those.

Unchanged

--since and --until behave exactly as before: they take YYYY-MM-DD, both bounds are inclusive, and either can stand alone. --last is refused beside them rather than quietly overriding them.

Full diff: [v0.3.1...v0.3.2]

v0.3.1

Choose a tag to compare

@kelesmert kelesmert released this 08 Aug 15:20

Two columns that never had anything to say, and a turn number that described a file.

Removed

Rate-limit windows, from the table and from the CSV. Claude Code writes none to a transcript and Codex fills one of the two, so the pair was mostly blank. The table is now fourteen columns instead of sixteen, and 156 characters instead of 174.

Changed

A turn's number is its place in the session, not the next line of a CSV. Watching one session from two directories used to number the same turn 16 and 7; it is now the same number from anywhere, and the same with no CSV at all.

The summary on exit describes the session, not the file. It used to reread the CSV, so a run that recorded nothing still reported that file's totals. It now agrees with the History: line above the table.

The CSV schema changed and an existing file will not open. The four rate-limit columns are gone, so a file written by 0.3.0 or earlier is refused and left untouched. Move or rename it and TurnLens starts a new one. Every command, flag and --json field works as it did.

Full diff: [v0.3.0...v0.3.1]

v0.3.0

Choose a tag to compare

@kelesmert kelesmert released this 05 Aug 01:12

Knowing when to update, what version you are on, and two numbers that were wrong.

Added

  • TurnLens says when a newer version is published. A global install pins
    whatever version was current when you ran it, which is how somebody on 0.1.1
    could miss that 0.2.0 had removed the flag they were using. Once a day,
    before a run starts, TurnLens asks the npm registry what is published and
    prints two lines if it is behind:

    TurnLens 0.3.0 is available. You have 0.2.0.
      npm install -g turnlens@latest
    

    It installs nothing and asks nothing, and silence is the normal outcome. The
    check is skipped under --offline, under NO_UPDATE_NOTIFIER set to any
    value, in CI, and whenever there is no terminal to print to. It adds no runtime
    dependency and no background process: the request rides along with the pricing
    request every run already makes, and it is eighteen bytes.

  • --version and -v, printing the bare version and nothing else. The tool
    previously had no way to report which version it was. Every help level names
    it, turnlens --help included, which is where somebody filing a bug report
    looks first.

Fixed

  • A narrowed report no longer overstates how many sessions it covers.
    turnlens report --since 2026-08-02 --until 2026-08-02 used to head the table
    35 sessions over 1 day when one session ran that day. Every session on the
    machine has to be opened, because which one holds a given day is knowable only
    by looking, so the count was of files read while the day count beside it
    counted only days that carried a turn. Now 1 of 35 sessions over 1 day, and
    still 35 sessions over 11 days when no date bound narrows anything.

    --json gains coverage.sessionsWithTurns beside coverage.sessions, and the
    same pair per agent. No existing field changed meaning.

  • --json is machine-readable under every flag again. Three messages shared
    stdout with the report: the --refresh-pricing result, the notice that pricing
    fell back to cached data, and the update notice. So
    turnlens report --json --refresh-pricing | jq failed on the first line. They
    are diagnostics rather than data and now go to stderr, where they still reach
    the terminal and no longer reach a pipe.


Nothing is removed or renamed in this release. Every 0.2.0 command, flag and
--json field works as it did, so upgrading needs no change to anything you have
scripted.

Full diff: v0.2.0...v0.3.0

v0.2.0

Choose a tag to compare

@kelesmert kelesmert released this 04 Aug 16:10

Reporting, a new commands and colour.

Breaking

--provider is removed. The agent is a positional argument.

turnlens --provider codex    # 0.1.x
turnlens codex               # 0.2.0

Naming no agent no longer means Codex. turnlens used to default to Codex
silently. It now asks which agent and lists that agent's sessions, and
turnlens report covers every agent rather than one.

Added

  • turnlens report, which counts what has already been spent across every
    session on the machine, without having watched any of them. It reads the
    agents' own transcripts, so it works whether or not TurnLens has ever run, and
    it writes nothing.
  • Four groupings, one word after report: daily (the default), weekly
    beginning Monday, monthly, and session.
  • --id, to watch or report on one session by full id or unique prefix. It
    works without an agent, because the id says which one.
  • --since and --until, inclusive, YYYY-MM-DD.
  • --json, machine-readable output carrying full model identifiers.
  • --compact, fewer columns whatever the terminal's width.
  • --no-color, alongside NO_COLOR and automatic detection of output that
    is not a terminal.
  • Colour, which only ever repeats what the text already says: headings cyan,
    rules dim, totals bold, and yellow for a turn that could not be priced and a
    turn you interrupted.
  • A summary of the turns a session had already closed, priced and printed on
    selection. They were previously invisible.
  • Codex archived sessions, now read when reporting. Watching still excludes
    them, because an archived session has ended and cannot be followed.

Fixed

  • A lock left behind by a process that is no longer running is reclaimed, and
    TurnLens says so. It previously had to be removed by hand.

Changed

  • The README is substantially rewritten, and now states that costs are
    API-equivalent rather than charges against a subscription.

Two behaviours that decide what a number means

  • A turn counts on the day you sent the prompt, not the day the answer
    finished. Otherwise the day would depend on how long the agent thought.
  • A report prices everything at today's rates. A CSV row keeps the rate of
    its own moment, so a report and a CSV can disagree on purpose.

Unchanged

Node 22 or newer, no runtime dependencies, Linux, macOS and Windows. Session
files are only ever read. Prompt previews stay off by default. The CSV schema and
its 27 columns are untouched, so files written by 0.1.1 are still appended to
rather than rejected.


TurnLens is pre-1.0, where a breaking change raises the minor version.

Full diff: v0.1.1...v0.2.0

v0.1.1 — first release

Choose a tag to compare

@kelesmert kelesmert released this 29 Jul 22:03

Notes on this version

0.1.1 changes documentation only. 0.1.0 was published by hand before its
README was updated, so the page on npm described the package as unreleased. There
is no code difference between the two.

See the README for the CSV
format, pricing behaviour, privacy details and known limits.