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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/env python3
"""self-ctx.py — measure the Architect's own context from its Claude Code transcript.
Why: the Architect's own tmux pane carries no `ctx N%` status-line field (its
sessions are skipped from fleet-poll.py's per-pane capture, itself included),
so the standing self-refresh rule (pause/clear/resume over 40% context) has
nothing in the pane to read. This module tails the newest INTERACTIVE
transcript *.jsonl Claude Code writes for this project instead. "Interactive"
matters: the same directory also fills with short-lived `claude -p --agent`
transcripts from any `claude -p` helper (the deferred question collector ran
one every few minutes), and a newest-by-mtime-alone pick can land on one of
those instead of the Architect's own multi-hour session, under-reporting its
context and never
alerting (trusty-tools review, 2026-09-27). Claude Code tags every line with
"entrypoint": "cli" for an interactive session and "sdk-cli" for `claude -p`;
this module filters on it.
What: `self_ctx_tokens(directory)` finds the newest *.jsonl (by mtime, among
only the CANDIDATE_LIMIT newest files so an sdk-cli-heavy directory stays
cheap to scan) whose tail carries entrypoint "cli", reads it from the tail
(growing the read window only if needed, never parsing the whole file up
front), and sums input_tokens + cache_read_input_tokens +
cache_creation_input_tokens from its last assistant `message.usage` object.
Returns None when the directory is missing or empty, no candidate is an
interactive ("cli") transcript, or the chosen one carries no assistant usage
line — this module never raises for that case; the caller (fleet-poll.py)
decides what a None means. `default_dir()` resolves the transcript directory
from CLAUDE_CONFIG_DIR and ARCHITECT_PROJECT_DIR, each with a documented
default, so no operator path is baked in.
Test: tests/test_self_ctx.py
"""
# `tm fleet init`'s default Architect project (#8436 ruling Q4).
=
# The Claude Code config dir trusty-mpm launches sessions under.
=
= 65536 # first tail read for usage; grows if not found in it
= 4096 # entrypoint is on nearly every line; a small tail suffices
= 20 # only this many newest-by-mtime files are considered
"""Claude Code's per-project transcript directory name for `path`: every
character that is not an ASCII letter or digit becomes "-"."""
return
"""<CLAUDE_CONFIG_DIR>/projects/<slug of ARCHITECT_PROJECT_DIR>, with
DEFAULT_CLAUDE_CONFIG_DIR and DEFAULT_PROJECT_DIR standing in for an
unset variable. `~` expands; the project path is made absolute first."""
=
=
=
return
"""Grow the tail read (start, x8, x64, ...) until `want(obj)` returns a
truthy result for some parsed JSON line, scanning newest-line-first, or
until the whole file has been read without a match. Returns `want`'s
result, or None. Malformed lines are skipped, not raised."""
=
return None
=
=
=
= # first line of a tail read may be a partial line
=
continue
=
continue
=
return
return None
=
"""The entrypoint ("cli" for interactive, "sdk-cli" for `claude -p`)
carried by the newest line in `path`, or None."""
return
"""Absolute path of the newest *.jsonl in `directory` whose entrypoint is
"cli" (an interactive session), or None. Only the `limit` newest files by
mtime are examined — cheapest (newest) first — so a directory shared with
a high-churn `claude -p` caller (entrypoint "sdk-cli") stays bounded."""
=
return None
return None
=
return
continue
return None
"""The last assistant `message.usage` dict in `path`, read from the tail.
Grows the read window instead of parsing the whole file, so a 100+ MB
transcript costs one small read in the common case where a recent line
carries usage.
"""
return None
return
return
"""input + cache_read + cache_creation tokens from the newest interactive
transcript's last assistant usage, or None if there is nothing to
measure."""
=
=
return None
=
return None
return + \
+