tokc 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tokc-0.1.0/LICENSE +21 -0
- tokc-0.1.0/PKG-INFO +299 -0
- tokc-0.1.0/README.md +265 -0
- tokc-0.1.0/pyproject.toml +49 -0
- tokc-0.1.0/setup.cfg +4 -0
- tokc-0.1.0/tests/test_tokc.py +441 -0
- tokc-0.1.0/tokc/__init__.py +3 -0
- tokc-0.1.0/tokc/__main__.py +3 -0
- tokc-0.1.0/tokc/budget.py +246 -0
- tokc-0.1.0/tokc/cli.py +816 -0
- tokc-0.1.0/tokc/config.py +183 -0
- tokc-0.1.0/tokc/discover.py +232 -0
- tokc-0.1.0/tokc/harness.py +252 -0
- tokc-0.1.0/tokc/html_report.py +229 -0
- tokc-0.1.0/tokc/model.py +304 -0
- tokc-0.1.0/tokc/report.py +395 -0
- tokc-0.1.0/tokc/rules.py +472 -0
- tokc-0.1.0/tokc/tokenizer.py +223 -0
- tokc-0.1.0/tokc/usage.py +329 -0
- tokc-0.1.0/tokc.egg-info/PKG-INFO +299 -0
- tokc-0.1.0/tokc.egg-info/SOURCES.txt +23 -0
- tokc-0.1.0/tokc.egg-info/dependency_links.txt +1 -0
- tokc-0.1.0/tokc.egg-info/entry_points.txt +2 -0
- tokc-0.1.0/tokc.egg-info/requires.txt +14 -0
- tokc-0.1.0/tokc.egg-info/top_level.txt +1 -0
tokc-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sylvain Mestre
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
tokc-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tokc
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Measure and shrink the token cost of Claude Code skills.
|
|
5
|
+
Author: Sylvain Mestre
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Shult/token_consumer
|
|
8
|
+
Project-URL: Repository, https://github.com/Shult/token_consumer
|
|
9
|
+
Project-URL: Issues, https://github.com/Shult/token_consumer/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/Shult/token_consumer/blob/main/CHANGELOG.md
|
|
11
|
+
Keywords: claude,claude-code,skills,tokens,cost,llm
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Provides-Extra: fast
|
|
24
|
+
Requires-Dist: tiktoken>=0.7; extra == "fast"
|
|
25
|
+
Provides-Extra: exact
|
|
26
|
+
Requires-Dist: anthropic>=0.40; extra == "exact"
|
|
27
|
+
Provides-Extra: yaml
|
|
28
|
+
Requires-Dist: pyyaml>=6; extra == "yaml"
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
31
|
+
Requires-Dist: tiktoken>=0.7; extra == "dev"
|
|
32
|
+
Requires-Dist: pyyaml>=6; extra == "dev"
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
# tokc — token consumption analyzer for Claude Code skills
|
|
36
|
+
|
|
37
|
+
[](https://github.com/Shult/token_consumer/actions/workflows/ci.yml)
|
|
38
|
+
[](https://pypi.org/project/tokc/)
|
|
39
|
+
[](https://pypi.org/project/tokc/)
|
|
40
|
+
[](LICENSE)
|
|
41
|
+
|
|
42
|
+
Measures what a skill actually costs you, tier by tier, and tells you where to cut.
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
29 skill(s) tokenizer: o200k_base x1.180 (default)
|
|
46
|
+
|
|
47
|
+
SKILL T1/sess T2/use T3 ALWAYS-ON TAX $/mo
|
|
48
|
+
------------------------------------------------------------------------------
|
|
49
|
+
project-artifact 241 5,415 8.5k ████████████████████████ ! $2.99
|
|
50
|
+
receipts 159 4,865 20k ████████████████ ! $2.40
|
|
51
|
+
hook-development 140 4,548 16k ██████████████ $2.20
|
|
52
|
+
...
|
|
53
|
+
------------------------------------------------------------------------------
|
|
54
|
+
TOTAL 2,787 99,352 294k $45.65
|
|
55
|
+
|
|
56
|
+
Always-on tax
|
|
57
|
+
2,787 tokens ride in the system prompt of every request, in every session,
|
|
58
|
+
whether or not any skill fires.
|
|
59
|
+
-> 2.9M billed token-equivalents/month at 200 sessions x 40 requests
|
|
60
|
+
|
|
61
|
+
Listing budget (characters, not tokens)
|
|
62
|
+
████████████████████████████████████████ 10,577 / 8,000 chars (132%)
|
|
63
|
+
! 2,577 chars over budget -- 6 skill(s) ship as `- name`, description omitted
|
|
64
|
+
demoted, least-used first: plugin-structure, project-artifact, receipts, ...
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Why this exists
|
|
68
|
+
|
|
69
|
+
Existing tools estimate skill cost by asking Claude — which costs tokens and gives
|
|
70
|
+
different numbers each run — or by running `tiktoken` over `SKILL.md`, which
|
|
71
|
+
**undercounts Claude by 15-20%** and, worse, reports a single number for something
|
|
72
|
+
that is not a single cost.
|
|
73
|
+
|
|
74
|
+
A skill is loaded in three tiers, billed at wildly different frequencies:
|
|
75
|
+
|
|
76
|
+
| Tier | What | Paid |
|
|
77
|
+
|---|---|---|
|
|
78
|
+
| **T1** | frontmatter `name` + `description` (+ `whenToUse`, which the listing appends) | in the system prompt of **every request, every session** |
|
|
79
|
+
| **T2** | the `SKILL.md` body | once per invocation |
|
|
80
|
+
| **T3** | `references/`, `scripts/`, … | only when Claude actually reads the file |
|
|
81
|
+
|
|
82
|
+
The number that matters is almost never the one people optimize. A 250-token
|
|
83
|
+
description is re-sent on every request of every session — with prompt caching that
|
|
84
|
+
is a **×5.15 multiplier per session** (1.25× cache write, then 0.10× per read).
|
|
85
|
+
A 6,000-token body that fires five times a month costs less than a 150-token
|
|
86
|
+
description that ships 200 times. `tokc` computes both and ranks accordingly.
|
|
87
|
+
|
|
88
|
+
## Install
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
pip install tokc # or: uvx tokc scan
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Zero hard dependencies. Three optional extras, none required:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
pip install "tokc[fast]" # tiktoken — much better offline counts
|
|
98
|
+
pip install "tokc[exact]" # anthropic — enables `--exact` and `tokc calibrate`
|
|
99
|
+
pip install "tokc[yaml]" # pyyaml — frontmatter edge cases
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Without them `tokc` falls back to a pure-python estimator and a minimal YAML
|
|
103
|
+
parser. Python 3.10+, Linux / macOS / Windows.
|
|
104
|
+
|
|
105
|
+
From source:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
git clone https://github.com/Shult/token_consumer && cd token_consumer
|
|
109
|
+
pip install -e ".[dev]" # tiktoken + pyyaml + pytest
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## What leaves your machine
|
|
113
|
+
|
|
114
|
+
Nothing, unless you ask for it. Worth stating plainly, because `tokc` reads
|
|
115
|
+
files that are more personal than the skills themselves:
|
|
116
|
+
|
|
117
|
+
**What it reads locally.** Your skill directories; `settings.json` for
|
|
118
|
+
`skillOverrides` and listing settings; `~/.claude.json` for the per-skill usage
|
|
119
|
+
counts that drive the listing order; your installed Claude Code build, to read
|
|
120
|
+
its own defaults out of the settings schema. `tokc setup` additionally scans
|
|
121
|
+
transcripts under `~/.claude`. From those it keeps four things and nothing else:
|
|
122
|
+
the session count, distinct `requestId`s, the *names* of invoked skills (from
|
|
123
|
+
`Skill` / `SlashCommand` tool-use blocks) and the recorded `skill_listing`
|
|
124
|
+
attachment. Prompts, responses and tool output are never retained, and what is
|
|
125
|
+
collected never leaves the summary figures written to your config file.
|
|
126
|
+
|
|
127
|
+
**What it sends.** Only `--exact` and `tokc calibrate` open a network
|
|
128
|
+
connection. They post skill text — frontmatter and body — to Anthropic's
|
|
129
|
+
`count_tokens` endpoint, using your own credentials, and get a token count back.
|
|
130
|
+
Every other command, and every default, is fully offline. `--no-config` ignores
|
|
131
|
+
saved answers entirely.
|
|
132
|
+
|
|
133
|
+
**What it writes.** `./.tokc.json` or `~/.claude/tokc.json` (`tokc setup`), a
|
|
134
|
+
baseline at `./.tokc-baseline.json` (`tokc snapshot`), and the HTML file you
|
|
135
|
+
name (`tokc report -o`). Nothing else on disk is modified — `tokc` never edits
|
|
136
|
+
your skills, it only tells you what to cut.
|
|
137
|
+
|
|
138
|
+
Both config files record local paths and usage figures, so keep them out of
|
|
139
|
+
version control:
|
|
140
|
+
|
|
141
|
+
```gitignore
|
|
142
|
+
.tokc.json
|
|
143
|
+
.tokc-baseline.json
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Commands
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
tokc setup # detect your harness, measure your usage, save both
|
|
150
|
+
tokc scan # every skill, ranked by always-on tax
|
|
151
|
+
tokc audit <name|path> # one skill: tiers, body heatmap, findings
|
|
152
|
+
tokc budget # simulate the system-prompt listing budget
|
|
153
|
+
tokc snapshot # record a baseline
|
|
154
|
+
tokc diff # what changed since the baseline
|
|
155
|
+
tokc watch <path> # live token counter while you edit
|
|
156
|
+
tokc report -o out.html # self-contained HTML report
|
|
157
|
+
tokc calibrate # measure the offline estimator against the real API
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
With no path, `tokc` scans the same roots Claude Code does: `~/.claude/skills`,
|
|
161
|
+
`<project>/.claude/skills`, and installed plugin skills.
|
|
162
|
+
|
|
163
|
+
### `tokc setup` — stop guessing
|
|
164
|
+
|
|
165
|
+
The numbers below only mean something if they match *your* harness and *your*
|
|
166
|
+
usage. `tokc setup` works both out and writes them to `./.tokc.json` (or
|
|
167
|
+
`~/.claude/tokc.json` with `--user`), which every other command then reads.
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
tokc setup # detect, measure, confirm
|
|
171
|
+
tokc setup -y # accept everything detected
|
|
172
|
+
tokc setup --harness other # a harness tokc cannot inspect: ask, don't assume
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Four things, in descending order of trust:
|
|
176
|
+
|
|
177
|
+
1. **A listing your harness actually sent.** Transcripts record the
|
|
178
|
+
`skill_listing` attachment verbatim, so we compare our reconstruction line by
|
|
179
|
+
line against the real thing — and recover the characters spent by skills
|
|
180
|
+
bundled *inside* the harness, which never appear on disk but still eat the
|
|
181
|
+
budget first.
|
|
182
|
+
2. **The installed build's own settings schema.** `skillListingMaxDescChars` and
|
|
183
|
+
`skillListingBudgetFraction` defaults are read out of the install (the VS Code
|
|
184
|
+
extension's schema, or the CLI binary), not hard-coded — so an upgrade that
|
|
185
|
+
changes them changes `tokc` too.
|
|
186
|
+
3. **Your transcripts.** Sessions, API requests per session (counted by distinct
|
|
187
|
+
`requestId`, not by message) and per-skill invocations over the last 30 days,
|
|
188
|
+
replacing the 200 / 40 / 20 defaults.
|
|
189
|
+
4. **You.** For a harness that cannot be probed — Claude Desktop, claude.ai, a
|
|
190
|
+
third-party client — nothing is assumed. `tokc` says it does not know and asks
|
|
191
|
+
whether the harness caps the listing at all.
|
|
192
|
+
|
|
193
|
+
Precedence runs weakest to strongest: probed defaults → `~/.claude/tokc.json` →
|
|
194
|
+
`./.tokc.json` → the live `settings.json` chain → `SLASH_COMMAND_TOOL_CHAR_BUDGET`
|
|
195
|
+
→ command-line flags. `--no-config` ignores the saved answers entirely.
|
|
196
|
+
|
|
197
|
+
### Tuning the cost model
|
|
198
|
+
|
|
199
|
+
Every projection is driven by explicit, overridable assumptions:
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
tokc scan --sessions 400 --requests 60 --invocations 10 --model claude-sonnet-5
|
|
203
|
+
tokc scan --no-cache # price without prompt caching (worst case)
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Accuracy
|
|
207
|
+
|
|
208
|
+
Three counting backends, picked automatically:
|
|
209
|
+
|
|
210
|
+
1. **`--exact`** — Anthropic's `count_tokens` endpoint. Exact. Needs credentials
|
|
211
|
+
(`ANTHROPIC_API_KEY`, or an `ant auth login` profile).
|
|
212
|
+
2. **tiktoken** — `o200k_base` × a calibration factor (default 1.18, the midpoint
|
|
213
|
+
of Anthropic's stated 15-20% undercount). Offline.
|
|
214
|
+
3. **heuristic** — pure python, no dependencies. Roughly ±10%.
|
|
215
|
+
|
|
216
|
+
`tokc calibrate` measures backend 2 against backend 1 **on your own skills** and
|
|
217
|
+
stores the corrected factor, so subsequent offline runs are accurate for your corpus.
|
|
218
|
+
|
|
219
|
+
## What it flags
|
|
220
|
+
|
|
221
|
+
Findings carry the tier they belong to and a savings estimate at the right rate —
|
|
222
|
+
a T1 win is multiplied by sessions, a T2 win by invocations.
|
|
223
|
+
|
|
224
|
+
**Tier 1 — the every-session tax**
|
|
225
|
+
- `T1-DESC-MISSING` / `T1-DESC-BLOAT` / `T1-DESC-TRUNCATED` — over
|
|
226
|
+
`skillListingMaxDescChars` the harness cuts mid-sentence and appends an
|
|
227
|
+
ellipsis, silently losing any trigger keywords at the end. The cap applies to
|
|
228
|
+
`description` and `whenToUse` **together**, since the listing shows the pair.
|
|
229
|
+
- `T1-HIDDEN` / `T1-NAME-ONLY` — `skillOverrides` in `settings.json` took this
|
|
230
|
+
skill out of the listing, or left it there without its description. Reported so
|
|
231
|
+
a zero is not mistaken for a saving.
|
|
232
|
+
- `T1-NO-TRIGGER` — nothing says *when* to use the skill, so you pay the tax and
|
|
233
|
+
never get the benefit. (Recognises English and French trigger phrasing.)
|
|
234
|
+
- `T1-FILLER` — "this skill is used to", "in order to", …
|
|
235
|
+
|
|
236
|
+
**Tier 2 — the per-invocation cost**
|
|
237
|
+
- `T2-BODY-LARGE`, `T2-SECTION-HOG` — one section dominating the body is the
|
|
238
|
+
extraction candidate.
|
|
239
|
+
- `T2-CODE-BLOCK`, `T2-BIG-TABLE` — reference material paid on every invocation.
|
|
240
|
+
- `T2-REPEAT` — lines repeated 3+ times (code fences excluded).
|
|
241
|
+
- `T2-HTML-COMMENT` — invisible when rendered, fully billed to the model.
|
|
242
|
+
- `T2-NO-STRUCTURE`, `T2-WHITESPACE`.
|
|
243
|
+
|
|
244
|
+
**Tier 3 — on-demand files**
|
|
245
|
+
- `T3-UNREFERENCED` — a bundled file `SKILL.md` never points at is unreachable.
|
|
246
|
+
- `T3-HUGE` — reading it will force compaction mid-task.
|
|
247
|
+
|
|
248
|
+
## CI
|
|
249
|
+
|
|
250
|
+
```bash
|
|
251
|
+
tokc budget --strict # exit 1 if the listing overflows and skills get dropped
|
|
252
|
+
tokc audit my-skill --strict # exit 1 on any HIGH finding
|
|
253
|
+
tokc diff --strict # exit 1 if the always-on tax grew
|
|
254
|
+
tokc scan --json # machine-readable
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## How the listing budget actually works
|
|
258
|
+
|
|
259
|
+
Worth stating precisely, because it is easy to get wrong in three ways at once:
|
|
260
|
+
|
|
261
|
+
1. **The budget is a character count, not a token count.** It is derived from the
|
|
262
|
+
context window — `window(tokens) × charsPerToken × fraction`, so
|
|
263
|
+
`200 000 × 4 × 0.01 = 8 000` by default — but what it caps is the *length of
|
|
264
|
+
the assembled listing text*. A model the harness does not recognise converts at
|
|
265
|
+
3 chars/token instead of 4, and the budget shrinks to 6 000.
|
|
266
|
+
2. **Nothing is dropped.** An entry that does not fit ships as `- name` with no
|
|
267
|
+
description. The skill stays listed and stays invocable by name; what it loses
|
|
268
|
+
is the text the model selects on.
|
|
269
|
+
3. **The order is neither arbitrary nor "largest first".** Entries are ranked by
|
|
270
|
+
`usageCount × max(0.5^(days_since_use / 7), 0.1)` — recorded in
|
|
271
|
+
`~/.claude.json` — and the best-ranked keep their descriptions, taken greedily,
|
|
272
|
+
so a small entry can still fit after a large one was refused. Skills bundled
|
|
273
|
+
inside the harness are exempt and consume the budget before any of yours.
|
|
274
|
+
|
|
275
|
+
`tokc` reproduces all three, reads the real usage ranking, and `tokc setup`
|
|
276
|
+
checks the result against a listing your harness genuinely sent.
|
|
277
|
+
|
|
278
|
+
## Caveats
|
|
279
|
+
|
|
280
|
+
- The **T1 multiplier** assumes 40 requests/session and a 5-minute cache TTL.
|
|
281
|
+
Override with `--requests`, or let `tokc setup` measure it; use `--no-cache` for
|
|
282
|
+
the uncached worst case.
|
|
283
|
+
- **T3 is excluded from projections.** Reference files load unpredictably, and
|
|
284
|
+
counting them would penalise exactly the progressive-disclosure structure this
|
|
285
|
+
tool tells you to adopt. They are reported, not projected.
|
|
286
|
+
- **Skills bundled in the harness are invisible on disk.** Without `tokc setup`
|
|
287
|
+
the budget simulation ignores them and is optimistic by a few thousand
|
|
288
|
+
characters. Setup recovers the figure from a real listing.
|
|
289
|
+
- **Only Claude Code is modelled.** The CLI and the VS Code extension share one
|
|
290
|
+
binary and one set of rules, read from the install. Claude Desktop, claude.ai
|
|
291
|
+
and third-party clients assemble the system prompt elsewhere; `tokc` will not
|
|
292
|
+
pretend to know their policy, and `tokc setup --harness other` asks instead.
|
|
293
|
+
- Offline counts are estimates until you run `tokc calibrate`.
|
|
294
|
+
|
|
295
|
+
## Tests
|
|
296
|
+
|
|
297
|
+
```bash
|
|
298
|
+
python -m pytest -q # 37 tests
|
|
299
|
+
```
|
tokc-0.1.0/README.md
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
# tokc — token consumption analyzer for Claude Code skills
|
|
2
|
+
|
|
3
|
+
[](https://github.com/Shult/token_consumer/actions/workflows/ci.yml)
|
|
4
|
+
[](https://pypi.org/project/tokc/)
|
|
5
|
+
[](https://pypi.org/project/tokc/)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
Measures what a skill actually costs you, tier by tier, and tells you where to cut.
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
29 skill(s) tokenizer: o200k_base x1.180 (default)
|
|
12
|
+
|
|
13
|
+
SKILL T1/sess T2/use T3 ALWAYS-ON TAX $/mo
|
|
14
|
+
------------------------------------------------------------------------------
|
|
15
|
+
project-artifact 241 5,415 8.5k ████████████████████████ ! $2.99
|
|
16
|
+
receipts 159 4,865 20k ████████████████ ! $2.40
|
|
17
|
+
hook-development 140 4,548 16k ██████████████ $2.20
|
|
18
|
+
...
|
|
19
|
+
------------------------------------------------------------------------------
|
|
20
|
+
TOTAL 2,787 99,352 294k $45.65
|
|
21
|
+
|
|
22
|
+
Always-on tax
|
|
23
|
+
2,787 tokens ride in the system prompt of every request, in every session,
|
|
24
|
+
whether or not any skill fires.
|
|
25
|
+
-> 2.9M billed token-equivalents/month at 200 sessions x 40 requests
|
|
26
|
+
|
|
27
|
+
Listing budget (characters, not tokens)
|
|
28
|
+
████████████████████████████████████████ 10,577 / 8,000 chars (132%)
|
|
29
|
+
! 2,577 chars over budget -- 6 skill(s) ship as `- name`, description omitted
|
|
30
|
+
demoted, least-used first: plugin-structure, project-artifact, receipts, ...
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Why this exists
|
|
34
|
+
|
|
35
|
+
Existing tools estimate skill cost by asking Claude — which costs tokens and gives
|
|
36
|
+
different numbers each run — or by running `tiktoken` over `SKILL.md`, which
|
|
37
|
+
**undercounts Claude by 15-20%** and, worse, reports a single number for something
|
|
38
|
+
that is not a single cost.
|
|
39
|
+
|
|
40
|
+
A skill is loaded in three tiers, billed at wildly different frequencies:
|
|
41
|
+
|
|
42
|
+
| Tier | What | Paid |
|
|
43
|
+
|---|---|---|
|
|
44
|
+
| **T1** | frontmatter `name` + `description` (+ `whenToUse`, which the listing appends) | in the system prompt of **every request, every session** |
|
|
45
|
+
| **T2** | the `SKILL.md` body | once per invocation |
|
|
46
|
+
| **T3** | `references/`, `scripts/`, … | only when Claude actually reads the file |
|
|
47
|
+
|
|
48
|
+
The number that matters is almost never the one people optimize. A 250-token
|
|
49
|
+
description is re-sent on every request of every session — with prompt caching that
|
|
50
|
+
is a **×5.15 multiplier per session** (1.25× cache write, then 0.10× per read).
|
|
51
|
+
A 6,000-token body that fires five times a month costs less than a 150-token
|
|
52
|
+
description that ships 200 times. `tokc` computes both and ranks accordingly.
|
|
53
|
+
|
|
54
|
+
## Install
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pip install tokc # or: uvx tokc scan
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Zero hard dependencies. Three optional extras, none required:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pip install "tokc[fast]" # tiktoken — much better offline counts
|
|
64
|
+
pip install "tokc[exact]" # anthropic — enables `--exact` and `tokc calibrate`
|
|
65
|
+
pip install "tokc[yaml]" # pyyaml — frontmatter edge cases
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Without them `tokc` falls back to a pure-python estimator and a minimal YAML
|
|
69
|
+
parser. Python 3.10+, Linux / macOS / Windows.
|
|
70
|
+
|
|
71
|
+
From source:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
git clone https://github.com/Shult/token_consumer && cd token_consumer
|
|
75
|
+
pip install -e ".[dev]" # tiktoken + pyyaml + pytest
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## What leaves your machine
|
|
79
|
+
|
|
80
|
+
Nothing, unless you ask for it. Worth stating plainly, because `tokc` reads
|
|
81
|
+
files that are more personal than the skills themselves:
|
|
82
|
+
|
|
83
|
+
**What it reads locally.** Your skill directories; `settings.json` for
|
|
84
|
+
`skillOverrides` and listing settings; `~/.claude.json` for the per-skill usage
|
|
85
|
+
counts that drive the listing order; your installed Claude Code build, to read
|
|
86
|
+
its own defaults out of the settings schema. `tokc setup` additionally scans
|
|
87
|
+
transcripts under `~/.claude`. From those it keeps four things and nothing else:
|
|
88
|
+
the session count, distinct `requestId`s, the *names* of invoked skills (from
|
|
89
|
+
`Skill` / `SlashCommand` tool-use blocks) and the recorded `skill_listing`
|
|
90
|
+
attachment. Prompts, responses and tool output are never retained, and what is
|
|
91
|
+
collected never leaves the summary figures written to your config file.
|
|
92
|
+
|
|
93
|
+
**What it sends.** Only `--exact` and `tokc calibrate` open a network
|
|
94
|
+
connection. They post skill text — frontmatter and body — to Anthropic's
|
|
95
|
+
`count_tokens` endpoint, using your own credentials, and get a token count back.
|
|
96
|
+
Every other command, and every default, is fully offline. `--no-config` ignores
|
|
97
|
+
saved answers entirely.
|
|
98
|
+
|
|
99
|
+
**What it writes.** `./.tokc.json` or `~/.claude/tokc.json` (`tokc setup`), a
|
|
100
|
+
baseline at `./.tokc-baseline.json` (`tokc snapshot`), and the HTML file you
|
|
101
|
+
name (`tokc report -o`). Nothing else on disk is modified — `tokc` never edits
|
|
102
|
+
your skills, it only tells you what to cut.
|
|
103
|
+
|
|
104
|
+
Both config files record local paths and usage figures, so keep them out of
|
|
105
|
+
version control:
|
|
106
|
+
|
|
107
|
+
```gitignore
|
|
108
|
+
.tokc.json
|
|
109
|
+
.tokc-baseline.json
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Commands
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
tokc setup # detect your harness, measure your usage, save both
|
|
116
|
+
tokc scan # every skill, ranked by always-on tax
|
|
117
|
+
tokc audit <name|path> # one skill: tiers, body heatmap, findings
|
|
118
|
+
tokc budget # simulate the system-prompt listing budget
|
|
119
|
+
tokc snapshot # record a baseline
|
|
120
|
+
tokc diff # what changed since the baseline
|
|
121
|
+
tokc watch <path> # live token counter while you edit
|
|
122
|
+
tokc report -o out.html # self-contained HTML report
|
|
123
|
+
tokc calibrate # measure the offline estimator against the real API
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
With no path, `tokc` scans the same roots Claude Code does: `~/.claude/skills`,
|
|
127
|
+
`<project>/.claude/skills`, and installed plugin skills.
|
|
128
|
+
|
|
129
|
+
### `tokc setup` — stop guessing
|
|
130
|
+
|
|
131
|
+
The numbers below only mean something if they match *your* harness and *your*
|
|
132
|
+
usage. `tokc setup` works both out and writes them to `./.tokc.json` (or
|
|
133
|
+
`~/.claude/tokc.json` with `--user`), which every other command then reads.
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
tokc setup # detect, measure, confirm
|
|
137
|
+
tokc setup -y # accept everything detected
|
|
138
|
+
tokc setup --harness other # a harness tokc cannot inspect: ask, don't assume
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Four things, in descending order of trust:
|
|
142
|
+
|
|
143
|
+
1. **A listing your harness actually sent.** Transcripts record the
|
|
144
|
+
`skill_listing` attachment verbatim, so we compare our reconstruction line by
|
|
145
|
+
line against the real thing — and recover the characters spent by skills
|
|
146
|
+
bundled *inside* the harness, which never appear on disk but still eat the
|
|
147
|
+
budget first.
|
|
148
|
+
2. **The installed build's own settings schema.** `skillListingMaxDescChars` and
|
|
149
|
+
`skillListingBudgetFraction` defaults are read out of the install (the VS Code
|
|
150
|
+
extension's schema, or the CLI binary), not hard-coded — so an upgrade that
|
|
151
|
+
changes them changes `tokc` too.
|
|
152
|
+
3. **Your transcripts.** Sessions, API requests per session (counted by distinct
|
|
153
|
+
`requestId`, not by message) and per-skill invocations over the last 30 days,
|
|
154
|
+
replacing the 200 / 40 / 20 defaults.
|
|
155
|
+
4. **You.** For a harness that cannot be probed — Claude Desktop, claude.ai, a
|
|
156
|
+
third-party client — nothing is assumed. `tokc` says it does not know and asks
|
|
157
|
+
whether the harness caps the listing at all.
|
|
158
|
+
|
|
159
|
+
Precedence runs weakest to strongest: probed defaults → `~/.claude/tokc.json` →
|
|
160
|
+
`./.tokc.json` → the live `settings.json` chain → `SLASH_COMMAND_TOOL_CHAR_BUDGET`
|
|
161
|
+
→ command-line flags. `--no-config` ignores the saved answers entirely.
|
|
162
|
+
|
|
163
|
+
### Tuning the cost model
|
|
164
|
+
|
|
165
|
+
Every projection is driven by explicit, overridable assumptions:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
tokc scan --sessions 400 --requests 60 --invocations 10 --model claude-sonnet-5
|
|
169
|
+
tokc scan --no-cache # price without prompt caching (worst case)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Accuracy
|
|
173
|
+
|
|
174
|
+
Three counting backends, picked automatically:
|
|
175
|
+
|
|
176
|
+
1. **`--exact`** — Anthropic's `count_tokens` endpoint. Exact. Needs credentials
|
|
177
|
+
(`ANTHROPIC_API_KEY`, or an `ant auth login` profile).
|
|
178
|
+
2. **tiktoken** — `o200k_base` × a calibration factor (default 1.18, the midpoint
|
|
179
|
+
of Anthropic's stated 15-20% undercount). Offline.
|
|
180
|
+
3. **heuristic** — pure python, no dependencies. Roughly ±10%.
|
|
181
|
+
|
|
182
|
+
`tokc calibrate` measures backend 2 against backend 1 **on your own skills** and
|
|
183
|
+
stores the corrected factor, so subsequent offline runs are accurate for your corpus.
|
|
184
|
+
|
|
185
|
+
## What it flags
|
|
186
|
+
|
|
187
|
+
Findings carry the tier they belong to and a savings estimate at the right rate —
|
|
188
|
+
a T1 win is multiplied by sessions, a T2 win by invocations.
|
|
189
|
+
|
|
190
|
+
**Tier 1 — the every-session tax**
|
|
191
|
+
- `T1-DESC-MISSING` / `T1-DESC-BLOAT` / `T1-DESC-TRUNCATED` — over
|
|
192
|
+
`skillListingMaxDescChars` the harness cuts mid-sentence and appends an
|
|
193
|
+
ellipsis, silently losing any trigger keywords at the end. The cap applies to
|
|
194
|
+
`description` and `whenToUse` **together**, since the listing shows the pair.
|
|
195
|
+
- `T1-HIDDEN` / `T1-NAME-ONLY` — `skillOverrides` in `settings.json` took this
|
|
196
|
+
skill out of the listing, or left it there without its description. Reported so
|
|
197
|
+
a zero is not mistaken for a saving.
|
|
198
|
+
- `T1-NO-TRIGGER` — nothing says *when* to use the skill, so you pay the tax and
|
|
199
|
+
never get the benefit. (Recognises English and French trigger phrasing.)
|
|
200
|
+
- `T1-FILLER` — "this skill is used to", "in order to", …
|
|
201
|
+
|
|
202
|
+
**Tier 2 — the per-invocation cost**
|
|
203
|
+
- `T2-BODY-LARGE`, `T2-SECTION-HOG` — one section dominating the body is the
|
|
204
|
+
extraction candidate.
|
|
205
|
+
- `T2-CODE-BLOCK`, `T2-BIG-TABLE` — reference material paid on every invocation.
|
|
206
|
+
- `T2-REPEAT` — lines repeated 3+ times (code fences excluded).
|
|
207
|
+
- `T2-HTML-COMMENT` — invisible when rendered, fully billed to the model.
|
|
208
|
+
- `T2-NO-STRUCTURE`, `T2-WHITESPACE`.
|
|
209
|
+
|
|
210
|
+
**Tier 3 — on-demand files**
|
|
211
|
+
- `T3-UNREFERENCED` — a bundled file `SKILL.md` never points at is unreachable.
|
|
212
|
+
- `T3-HUGE` — reading it will force compaction mid-task.
|
|
213
|
+
|
|
214
|
+
## CI
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
tokc budget --strict # exit 1 if the listing overflows and skills get dropped
|
|
218
|
+
tokc audit my-skill --strict # exit 1 on any HIGH finding
|
|
219
|
+
tokc diff --strict # exit 1 if the always-on tax grew
|
|
220
|
+
tokc scan --json # machine-readable
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## How the listing budget actually works
|
|
224
|
+
|
|
225
|
+
Worth stating precisely, because it is easy to get wrong in three ways at once:
|
|
226
|
+
|
|
227
|
+
1. **The budget is a character count, not a token count.** It is derived from the
|
|
228
|
+
context window — `window(tokens) × charsPerToken × fraction`, so
|
|
229
|
+
`200 000 × 4 × 0.01 = 8 000` by default — but what it caps is the *length of
|
|
230
|
+
the assembled listing text*. A model the harness does not recognise converts at
|
|
231
|
+
3 chars/token instead of 4, and the budget shrinks to 6 000.
|
|
232
|
+
2. **Nothing is dropped.** An entry that does not fit ships as `- name` with no
|
|
233
|
+
description. The skill stays listed and stays invocable by name; what it loses
|
|
234
|
+
is the text the model selects on.
|
|
235
|
+
3. **The order is neither arbitrary nor "largest first".** Entries are ranked by
|
|
236
|
+
`usageCount × max(0.5^(days_since_use / 7), 0.1)` — recorded in
|
|
237
|
+
`~/.claude.json` — and the best-ranked keep their descriptions, taken greedily,
|
|
238
|
+
so a small entry can still fit after a large one was refused. Skills bundled
|
|
239
|
+
inside the harness are exempt and consume the budget before any of yours.
|
|
240
|
+
|
|
241
|
+
`tokc` reproduces all three, reads the real usage ranking, and `tokc setup`
|
|
242
|
+
checks the result against a listing your harness genuinely sent.
|
|
243
|
+
|
|
244
|
+
## Caveats
|
|
245
|
+
|
|
246
|
+
- The **T1 multiplier** assumes 40 requests/session and a 5-minute cache TTL.
|
|
247
|
+
Override with `--requests`, or let `tokc setup` measure it; use `--no-cache` for
|
|
248
|
+
the uncached worst case.
|
|
249
|
+
- **T3 is excluded from projections.** Reference files load unpredictably, and
|
|
250
|
+
counting them would penalise exactly the progressive-disclosure structure this
|
|
251
|
+
tool tells you to adopt. They are reported, not projected.
|
|
252
|
+
- **Skills bundled in the harness are invisible on disk.** Without `tokc setup`
|
|
253
|
+
the budget simulation ignores them and is optimistic by a few thousand
|
|
254
|
+
characters. Setup recovers the figure from a real listing.
|
|
255
|
+
- **Only Claude Code is modelled.** The CLI and the VS Code extension share one
|
|
256
|
+
binary and one set of rules, read from the install. Claude Desktop, claude.ai
|
|
257
|
+
and third-party clients assemble the system prompt elsewhere; `tokc` will not
|
|
258
|
+
pretend to know their policy, and `tokc setup --harness other` asks instead.
|
|
259
|
+
- Offline counts are estimates until you run `tokc calibrate`.
|
|
260
|
+
|
|
261
|
+
## Tests
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
python -m pytest -q # 37 tests
|
|
265
|
+
```
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
# 77+ for PEP 639 (`license` as an SPDX string, `license-files`).
|
|
3
|
+
requires = ["setuptools>=77"]
|
|
4
|
+
build-backend = "setuptools.build_meta"
|
|
5
|
+
|
|
6
|
+
[project]
|
|
7
|
+
name = "tokc"
|
|
8
|
+
version = "0.1.0"
|
|
9
|
+
description = "Measure and shrink the token cost of Claude Code skills."
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
license = "MIT"
|
|
13
|
+
license-files = ["LICENSE"]
|
|
14
|
+
authors = [{ name = "Sylvain Mestre" }]
|
|
15
|
+
keywords = ["claude", "claude-code", "skills", "tokens", "cost", "llm"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Environment :: Console",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.10",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Programming Language :: Python :: 3.13",
|
|
24
|
+
"Topic :: Software Development :: Quality Assurance",
|
|
25
|
+
]
|
|
26
|
+
dependencies = []
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
Homepage = "https://github.com/Shult/token_consumer"
|
|
30
|
+
Repository = "https://github.com/Shult/token_consumer"
|
|
31
|
+
Issues = "https://github.com/Shult/token_consumer/issues"
|
|
32
|
+
Changelog = "https://github.com/Shult/token_consumer/blob/main/CHANGELOG.md"
|
|
33
|
+
|
|
34
|
+
[project.optional-dependencies]
|
|
35
|
+
# tiktoken makes offline counts far better than the pure-python fallback.
|
|
36
|
+
fast = ["tiktoken>=0.7"]
|
|
37
|
+
# anthropic enables `--exact` and `tokc calibrate`.
|
|
38
|
+
exact = ["anthropic>=0.40"]
|
|
39
|
+
yaml = ["pyyaml>=6"]
|
|
40
|
+
dev = ["pytest>=8", "tiktoken>=0.7", "pyyaml>=6"]
|
|
41
|
+
|
|
42
|
+
[project.scripts]
|
|
43
|
+
tokc = "tokc.cli:main"
|
|
44
|
+
|
|
45
|
+
[tool.setuptools]
|
|
46
|
+
packages = ["tokc"]
|
|
47
|
+
|
|
48
|
+
[tool.pytest.ini_options]
|
|
49
|
+
testpaths = ["tests"]
|
tokc-0.1.0/setup.cfg
ADDED