1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#!/bin/sh
# trusty-mpm-commit-stats: v3
#
# Stamp the commit message with the session's token counts, savings percentage
# and model id, as git trailers (#7074). Installed by trusty-mpm into the
# repository's effective hooks directory, which every worktree of a base clone
# shares.
#
# This hook must never block a commit. Every branch below exits 0, and the
# stamping command is invoked with its output discarded: a missing `tm`, a
# session with nothing recorded, or a `tm` that fails outright all leave the
# message exactly as git wrote it.
#
# It must also never DELAY a commit. `git` blocks here, so the stamper runs
# under a wall-clock budget and is killed if it outruns it; the commit then
# proceeds with no stats block. `tm commit-trailers` already caps how much of
# the transcript it reads, so this budget is the second bound, for a read that
# is slow for a reason the byte cap does not cover — a stalled network mount,
# a machine under load.
#
# Set TM_SKIP_COMMIT_STATS=1 to turn it off for one commit, or
# TM_COMMIT_STATS_TIMEOUT to a whole number of seconds to change the budget.
#
# Git's SECOND argument says where the message came from, and the footer means
# something different for each source (#7249). Tokens are a property of one
# session's work on one message:
#
# merge git built the message from the merge's parents. The tokens of
# whoever ran `git merge` describe none of it. No stamping.
# squash the message is assembled by git or GitHub from a branch's
# commits, each with its own figures. No stamping.
# commit the message comes from an existing commit — a cherry-pick, a
# revert, `--amend`, `-c`/`-C`. Any block in it belongs to the
# session that made the ORIGINAL commit, so it is STRIPPED and this
# session's figures are stamped in its place. With no current
# session the strip still happens and nothing is added: no block is
# correct where another session's block is not. This is the one
# source that runs the stamper outside a Claude Code session.
# message `-m` / `-F`, and `template` — the message is this commit's own.
# Stamped, as is the empty source git passes for an editor commit.
#
# `tm commit-trailers` is handed the source and applies the same rules, so the
# `merge` and `squash` arms below are the cheap short-circuit rather than the
# decision. Stamping stays idempotent WITHIN a source: a re-run over a message
# this session already stamped adds nothing.
[ &&
commit_source=""
# Only a commit made inside a Claude Code session has stats to report — except
# a reused message, which may carry another session's stats to remove.
if [ && [; then
fi
||
budget=""
&
stamper=
# Poll in tenths of a second so a stamper that finishes in milliseconds — the
# ordinary case — costs no measurable wait. A `sleep` that rejects a fractional
# argument fails immediately without sleeping, so the fallback second is
# charged as the ten tenths it is.
elapsed=0
limit=
while [; do
|| break
if ; then
elapsed=
else
elapsed=
fi
done
if ; then
fi