Measured 2026-08-29 · rtk 0.46.0 · macOS
Two people replied to the thread saying RTK costs them tokens rather than saving them. The savings are real and large. So is the failure they describe. Everything below was measured on this machine today, not reasoned about.
↓ הסבר מלא בעברית: מה בדיוק הם טוענים
01 · the headline
rtk gain reports 64.6M tokens saved across 47,075 proxied commands, a 31.2%
average reduction on 206.9M input tokens. That number is true. It is also an average over
wildly different commands, and the average is the least useful way to read it.
Top 10 by tokens saved. Percentages are RTK's own average reduction for that command.
One row carries the whole story: 568 test runs saved 28.6M tokens, which is 44% of everything RTK has ever saved here. A test runner's summary genuinely is the useful output, so compressing the other 15% of its log costs nothing.
02 · concentration
Split the 64.6M by what kind of command earned it. Test and lint runners (vitest, pytest, eslint) are 623 commands, 1.3% of the total, and they account for 29.6M. Search and read (grep, read, find) are 9,448 commands, 20% of the total, for 23.3M.
Segments sum to 64.5M against a reported 64.6M total. The gap is rounding in RTK's own display.
| Family | commands | share of cmds | saved | share of savings |
|---|---|---|---|---|
| test + lint runners | 623 | 1.3% | 29.6M | 46% |
| search + read | 9,448 | 20.1% | 23.3M | 36% |
| process snapshots | 29 | 0.1% | 2.4M | 4% |
| gh pr diff | 175 | 0.4% | 1.3M | 2% |
| everything else | 36,800 | 78.2% | 7.9M | 12% |
This matters because the two halves carry different risk. The runner half has no retry risk: nobody needs line 400 of a passing vitest log. The search half is where the complaint lives.
03 · the complaint
@TheOnlyKatz, 2026-08-29 01:10
RTK תמיד היה רק מבזבז לי טוקנים ולא חוסך, לא חסרות פקודות שהסוכן מנסה לבצע שעם RTK לא מחזירות באמת את המידע ההכרחי ואז הוא צריך לעשות עוד 10 איטרציות עם RTK כדי לקבל את המידע.
RTK only ever wasted tokens for me. Plenty of commands do not return the information the agent needs, so it takes another 10 iterations to get it.
@RonSher160268, 2026-08-29 05:18
גם משתמש ב rtk. היו כמה פעמים שהסוכן היה צריך לעקוף את זה כי ה output לא הכיל משהו. מתחיל לחשוב שהחיסכון פה זה אשליה ואולי זה גורם לסוכנים לעבוד יותר
Also an RTK user. Several times the agent had to bypass it because the output was missing something. Starting to think the saving is an illusion and it may make agents work more.
I ran 20 (pattern, file) pairs through plain grep and
rtk grep on real repository files, from inside a script file, which the hook
cannot rewrite, so grep was genuinely plain. The divergence is deterministic:
rtk grep prints at most 25 matches. Thirteen pairs matched exactly, every one of them
at or under 25. Seven diverged, every one of them over 25. Zero divergences below the ceiling.
The seven pairs that diverged. In all seven, RTK printed exactly 25 matches.
| Pattern | File | true | shown | Verdict |
|---|
04 · deep dive · עברית
RTK הוא לא ספרייה ולא MCP. הוא הוק מסוג PreToolUse שיושב על כלי ה־Bash של
Claude Code. לפני שכל פקודת שורת פקודה רצה, ההוק מיירט את מחרוזת הפקודה, שואל את הבינארי
של RTK אם יש לה מקבילה מקוצרת, ואם יש, מחליף אותה.
הסוכן ביקש grep -n hook README.md. מה שרץ בפועל הוא
rtk grep -n hook README.md. הפלט שחוזר לתוך ההקשר של הסוכן הוא הפלט המקוצר,
וזו בדיוק הנקודה: הסוכן קיבל תשובה אחרת מזו שהוא ביקש, והוא לא בהכרח מודע לכך.
מדדתי את המנגנון שעומד מאחורי הטענה הראשונה, והוא קיים ומדויק:
rtk grep מדפיס לכל היותר 25 התאמות, לא משנה כמה יש באמת. בקובץ
src/hooks/README.md יש 219 שורות שמכילות את המילה hook.
RTK מדפיס 25 מהן.
ההבדל הקריטי הוא בין קריאה לבין חיפוש. כשקוראים קובץ, 25 השורות הראשונות הן התחלה סבירה. כשמחפשים, ההתאמה שמעניינת אותך יכולה להיות מספר 40, ואין שום סיבה שהיא תהיה בין 25 הראשונות.
יש כאן גם סיכון חמור יותר מבזבוז זמן, וזה מה ש־Ron מתאר כ־"the output לא הכיל משהו": היעדר שקרי. אם הסוכן מסיק "המחרוזת הזו לא קיימת" כשהיא כן קיימת בשורה 100, הוא לא סתם מבזבז תור. הוא בונה על מסקנה שגויה. זה בדיוק מה שקרה לי ב־24 באוגוסט, ובגלל זה כתבתי אז פתק זיכרון על הנושא.
RTK לא משקר ולא מסתיר. הוא מודיע על הקיצוץ פעמיים, בהתחלה ובסוף:
219 matches in 1 files: 3:TypeScript hook system for the OrchestKit Claude Plugin... ... 66:│ │ ├── mcp/ # MCP integration hooks +194 more in src/hooks/README.md [see remaining: tail -n +26 "$HOME/.../1787985624_grep_0_s_da1929.log"]
השורה הראשונה אומרת שיש 219 התאמות. השורה האחרונה אומרת ש־194 נחתכו, ונותנת את הפקודה המדויקת לשלוף אותן. כלומר המידע לשבור את הלולאה נמצא שם, בתוך הפלט.
אבל שים לב שזה עובד רק אם שני תנאים מתקיימים: הסוכן צריך לקרוא את הכותרת ואת
הכותרת התחתונה, והוא צריך לבחור להריץ את ה־tail במקום פשוט לנסח מחדש
את החיפוש. שתי ההתנהגויות האלה אינן מובטחות. וגם כשהוא כן מריץ את ה־tail,
זו עדיין קריאה שנייה, כלומר תור נוסף. כלומר החוויה שהם מתארים נשארת נכונה, היא פשוט
פחות דרמטית ממה שהם חושבים.
כמה זה קורה בפועל? כל קיצוץ כותב קובץ יומן. תיקיית היומנים מחזיקה בערך עשרה ימים,
ויש בה 7 קיצוצים של grep, אחד מהם נוצר על ידי הבדיקה הזו עצמה. כלומר שישה
אירועים אמיתיים בעשרה ימים של עבודה כבדה. זה שיעור נמוך.
זו הטענה החכמה בשרשור, והיא נכונה ברמה מבנית. RTK מודד כמה בייטים הוא הוריד
מפקודה אחת. אין לו שום שדה בשביל הקריאה השנייה שהוא עצמו גרם לה. אם הסוכן מריץ אחר
כך את ה־tail שהוצע לו, RTK רושם אותה כפקודה נפרדת בחיסכון של בערך אפס אחוז.
מה שהמדד רואה מה שקרה באמת
───────────────────── ──────────────────────────────
rtk grep -97.9% WIN rtk grep 2,004 tok קוצץ
rtk tail ~900 tok שליפה
─────────────────────────
נרשם: ניצחון אחד בפועל: שתי קריאות, שני תורות
לכן "החיסכון הוא אשליה" הוא ניסוח חזק מדי, כי 46 אחוז מהחיסכון מגיע מ־623 הרצות של בדיקות, ושם אין שום סיכון ללולאה. אבל "המדד הזה לא יכול להוכיח שהוא לא אשליה" הוא ניסוח מדויק לחלוטין, וזה מה שנכון להודות בו.
זו הטענה היחידה בשרשור שלא שורדת מדידה, וכדאי לתקן אותה. Amit ענה שהכלי הוא
plug & play ושההגדרה היחידה הרלוונטית היא
config.exclude_commands. הוא צודק, ובדקתי גם למה:
rtk grep יש דגל
-m, --max עם ברירת מחדל 200. הרצתי אותו עם 200, עם 500 ועם 1000. בכל
שלוש הפעמים חזרו בדיוק 25 התאמות ובדיוק 2,003 בייטים. הדגל אינרטי.grep לגמרי, וזה מוותר על 16.8 מיליון טוקנים של חיסכון אמיתי.הרצתי rtk gain --all וקיבלתי פירוק ל־88 ימים. וזה משנה את כל הוויכוח.
אחוז החיסכון היומי נע בין 0.2 אחוז ל־99.7 אחוז. אין יום טיפוסי. הממוצע של 31.2 אחוז
לא מתאר אף יום אמיתי, והוא בדיוק המספר שעליו מתווכחים בשרשור.
כלומר זה לא כלי עם הנחה קבועה של 31 אחוז. זה כלי שבחלק מסוגי העבודה הוא כמעט כסף חינם, ובחלק אחר הוא תקורה נטו. הממוצע מסתיר איזה מהשניים אתה חווה כרגע.
ולכן ייתכן מאוד ש־Amit ו־Ron פשוט חיים במצב השני. אם העבודה שלהם לא מייצרת פלטים ענקיים, RTK מסנן פלט שלא היה נפוח מלכתחילה, החיסכון זניח, ועלות הקיצוץ לא מתקזזת. ה־31.2 אחוז שלי הוא לא ראיה נגד החוויה שלהם, כי ה־31.2 אחוז שלי הוא בעצמו תערובת של ימים של 99.7 אחוז וימים של 0.2 אחוז.
ל־RTK יש פקודה שלישית שאף אחד בשרשור לא הריץ, rtk cc-economics. היא
מצליבה את החיסכון שלו מול ההוצאה בפועל, וזו התצוגה היחידה שמתרגמת טוקנים לכסף.
RTK רואה רק פלט של פקודות שנכנס להקשר. הוא לא נוגע ולא יכול לגעת בקריאות מטמון, ושם נמצא כמעט כל התשלום. לכן החיסכון אמיתי, אבל הוא חצי אחוז מהחשבון, ושום כוונון של תקרת ה־grep לא ישנה את היחס הזה.
שים לב גם שלשלושת המספרים הראשיים של RTK יש פער של שתי סדרי גודל ביניהם: 31.2 אחוז (ממוצע שמערבב ימים של 0.2 עם ימים של 99.7), 54.2 אחוז "מהמכסה החודשית" (שמשווה חיסכון של כתשעים יום מול מכסה של חודש אחד, כלומר מנופח פי שלושה בציר הזמן), ו־0.5 אחוז מהכסף. האחרון הוא היחיד שאני מוכן להגן עליו.
בדקתי שלושה כפתורים מתועדים שאמורים להרים את התקרה, וכולם מתים:
-m/--max בשורת הפקודה, grep_max_per_file בקובץ ההגדרות (בדקתי
גם 5, שהיה אמור להקטין, ולא קרה כלום), ו־--ultra-compact. מה שכן עובד זה
exclude_commands, והוא מדויק: אחרי שהוספתי grep -q, הוא הפסיק
לעבור דרך RTK בזמן ש־grep -n המשיך לחסוך את 16.8 המיליון שלו.
בהתחלה טענתי שההוק של RTK לא עובד על המכונה הזו. טעיתי, ובדקתי את זה כמו שצריך: Claude Code רושם כל הרצת הוק כקובץ מצורף על הקריאה עצמה, עם הפלט של ההוק. על פני שבעה ימים ו־16,493 פקודות Bash, ההוק שכתב 96.6 אחוז מהפקודות שהוא מסוגל לשכתב. הוא עובד.
הבעיה האמיתית אחרת לגמרי: רק 13 אחוז מהפקודות הן בצורה ש־RTK יודע לשכתב. 46 אחוז הן קבצי סקריפט שנכתבים דרך heredoc, ו־RTK לא רואה מה יש בתוך heredoc. זה לא מקרה. יש לי כלל גלובלי שאומר "פקודות ארוכות או מרובות שלבים, תכתוב לקובץ ותריץ אותו", והוק שמזכיר את זה בכל פרומפט, מסיבה טובה: גלישת שורות בטרמינל מפרידה דגל מהארגומנט שלו. הכלל עושה את עבודתו. והוא גם, בשקט, הסיבה הכי גדולה ש־RTK נוגע ב־13 אחוז מהפקודות במקום ב־50.
שני מנגנוני הגנה שלי נלחמו זה בזה, ואף אחד מהם לא יכול היה לראות את השני. זו לא תקלה לתקן, זו הכרעה לקבל עם המספרים מול העיניים.
| הטענה | הפסיקה | הראיה |
|---|---|---|
| RTK חוסך הרבה טוקנים | מחזיק | 64.6 מיליון על פני 47,075 פקודות |
| RTK מחזיר פלט חסר | מחזיק | תקרה של 25 התאמות, שוחזרה ב־7 מתוך 20 |
| וזה עולה באיטרציות נוספות | חלקית | מוצהר בכותרת ובתחתית, ושישה אירועים בעשרה ימים |
| החיסכון הוא אשליה | חצי | נכון לגבי צורת המדידה, לא נכון לגבי חצי ההרצות |
| "אז לא הגדרת טוב" | לא נתמך | התקרה היא ברירת מחדל, והדגל שהיה אמור לשנות אותה לא עובד |
כל המספרים כאן נמדדו על המכונה הזו ב־29 באוגוסט 2026, מול rtk 0.46.0. אפשר לשחזר כל אחד מהם בפקודה אחת.
05 · the part the thread missed
The capped output opens with the true total and closes with the shortfall plus the exact recovery command:
$ rtk grep -n "hook" src/hooks/README.md 219 matches in 1 files: 3:TypeScript hook system for the OrchestKit Claude Plugin... ... 66:│ │ ├── mcp/ # MCP integration hooks +194 more in src/hooks/README.md [see remaining: tail -n +26 "$HOME/.../1787985624_grep_0_s_da1929.log"]
That call went from 93,281 bytes to 2,004 bytes, a 97.9%
reduction, while stating up front that 219 matches exist and 194 are one tail
away. So this is not a silent lie. It is a disclosed trade with a documented escape hatch,
and it only breaks when the agent skips the header or prefers to reformulate over running
the tail.
Two corrections to my own prior notes while I am here. First, the case recorded on
2026-08-24, where grep supposedly could not find a string at line 991 of
cc-triage.mjs, does not reproduce on 0.46.0: all six matches come back.
Second, I earlier called the ceiling 26. It is 25. I had been counting RTK's own
N matches in 1 files: header line as a match.
06 · the knob that does not turn
There are two documented ways to raise the ceiling and a third documented way to compress harder. All three are inert. If any of them worked, the ceiling would be a configuration question and "you configured it wrong" would have a leg to stand on.
1. The CLI flag. rtk grep --help advertises
-m, --max <MAX> Max results to show [default: 200].
| Invocation | matches | bytes |
|---|---|---|
rtk grep -n hook README.md | 25 | 2,003 |
... -m 200 | 25 | 2,003 |
... -m 500 | 25 | 2,003 |
... -m 1000 | 25 | 2,003 |
2. The config key. RTK's own
config --create template, and the upstream docs, both ship a
[limits] block whose grep_max_per_file = 25 is exactly the ceiling
I measured. Tested against the real config file, with a backup, in both directions:
grep_max_per_file | matches printed |
|---|---|
| absent (baseline) | 25 |
| 300 | 25 |
| 60 | 25 |
| 5 | 25 |
The 5 row is the decisive one: a value below
the ceiling should have shrunk the output, and did not. The positive control matters here,
because a config that is never read looks identical to a key that is ignored. Setting
[tee] enabled = false in the same file visibly changed the output, dropping the
[see remaining: tail ...] hint from the footer. So the file is read and this
key is ignored.
3. The compression flag. --ultra-compact,
documented as a global "Level 2 optimizations" flag:
| Command | normal | ultra | delta |
|---|---|---|---|
rtk grep -n hook README.md | 2,003 B | 2,003 B | 0.0% |
rtk ls -la src/hooks | 541 B | 541 B | 0.0% |
rtk git status | 127 B | 127 B | 0.0% |
rtk git log -20 | 6,314 B | 6,314 B | 0.0% |
Same class of defect already found in rtk rewrite,
whose --help promises exit 0 or 1 and which actually exits 3 with the rewrite on
stdout. Documented contract, different behaviour.
What does work is [hooks] exclude_commands, and it is precise. After
adding "grep -q", grep -q stopped being rewritten while
grep -n kept its 16.8M. The list to add comes from
rtk gain --failures, which logs 7,688 parse failures at a 100% recovery
rate: grep -q 673 times (a predicate, where the exit code is the answer),
uv sync 96, git stash 13, docker ps --format 8.
Those are commands paying the RTK detour for nothing.
07 · adjudication
| Claim | Verdict | Evidence |
|---|---|---|
| RTK saves a lot of tokens | HOLDS | 64.6M over 47,075 commands, 31.2% average |
| RTK returns incomplete output | HOLDS | 25 match ceiling, reproduced in 7 of 20 pairs |
| ...and that costs extra iterations | BOUNDED | disclosed twice; six real spills in ten days |
| The saving is an illusion | HALF | true of the accounting, false of the runner half |
| "You did not configure it properly" | NOT SUPPORTED | default behaviour, and -m is documented but inert |
08 · the time series
rtk gain --all breaks the lifetime figure into 88 days. Daily reduction ranges
from 0.2% to 99.7%. There is no typical day. Averaging across that distribution produces
a number that describes none of it, and it is the number the thread is arguing about.
Bar width is total input tokens, so it shows volume and rate on one axis. May 2026 is omitted at 82.7K input, too small to draw.
July is the interesting month: the highest volume by far, and the worst rate. Three days explain almost all of it.
| Day | input | saved | rate |
|---|---|---|---|
| 2026-07-29 | 67.4M | 2.2M | 3.2% |
| 2026-07-26 | 20.0M | 506.9K | 2.5% |
| 2026-07-15 | 18.8M | 38.9K | 0.2% |
| those three | 106.2M | 2.7M | 2.6% |
| 2026-08-06 | 12.0M | 11.9M | 99.7% |
| 2026-06-11 | 12.2M | 11.7M | 95.4% |
| 2026-07-24 | 7.1M | 6.8M | 96.2% |
| those three | 31.3M | 30.4M | 97.1% |
Read those two blocks together. Three days carried 51% of every token RTK has ever seen and produced 4% of the savings. Three other days produced 47% of all savings. This is not a tool with a 31% discount rate. It is a tool that is nearly free money on some workloads and pure overhead on others, and the lifetime average hides which one you are having.
That reframes the whole argument. Amit and Ron are not necessarily wrong about their own machines: they may simply be living in the low-compression mode, where RTK filters output that was never bulky to begin with and the truncation cost is not offset. My 31.2% is not evidence against their experience, because my own 31.2% is itself a blend of 99.7% days and 0.2% days.
09 · the money
RTK ships a third view nobody in the thread ran. rtk cc-economics joins its
own savings against ccusage's spend figure, and it is the only view that converts tokens into
money. It is also the one that settles the argument.
Spent (ccusage): $78,041.36 Input: 194.5M Output: 203.0M Cache writes: 3,114.6M Cache reads: 75,164.4M <-- RTK cannot touch any of this RTK commands: 47,122 Tokens saved: 65.1M Estimated savings: $402.56 (0.5%)
Cache reads are 75.2 billion tokens against 194.5M of fresh input. RTK only ever sees command output entering context, which is a rounding error next to where the spend actually lives. So the savings are real, they are just 0.5% of the bill, and no amount of tuning the grep ceiling changes that ratio.
Which makes RTK's three headline numbers worth ranking, because they disagree with each other by two orders of magnitude:
| Source | Claim | Trust |
|---|---|---|
rtk gain | 31.2% average reduction | low averages 0.2% days with 99.7% days |
rtk gain -q | 54.2% of monthly quota preserved | lowest compares lifetime savings (about 90 days) against a monthly quota |
rtk cc-economics | $402.56, 0.5% of spend | highest |
One caveat kept honest: ccusage prices tokens at API list rates, so $78,041 is list-price-equivalent value rather than cash paid on a subscription. The 0.5% ratio survives that, because both sides of it are priced the same way.
10 · and on this machine
Two earlier versions of this section claimed the hook was not firing and diagnosed why.
Both diagnoses were wrong, and so was the claim. The transcript settles it: Claude Code
records every hook run as an attachment on the tool call, with the hook's stdout, and RTK's
stdout carries the literal string RTK auto-rewrite. That is a per-call record,
not an inference.
| Session (today) | bash calls | rewritable | rewritten | missed |
|---|---|---|---|---|
| 7ea749b7 (platform) | 235 | 77 | 79 | 0 |
| a8f68ce0 (platform) | 156 | 52 | 51 | 1 |
| e916de50 (platform) | 307 | 21 | 21 | 0 |
| 2d9d60ae (core) | 341 | 38 | 39 | 0 |
| 8a1bf14f (orchestkit) | 356 | 2 | 2 | 0 |
| 553b7d75 (this one) | 81 | 8 | 8 | 0 |
The two commands I offered as proof of a dead hook were both misread, in different ways:
| My "proof" | What was true |
|---|---|
git log --oneline -5 came back native, counter did not move |
It was rewritten; the transcript has the attachment. rtk git log --oneline output is byte-identical to native (395 B = 395 B), and the counter buffers. |
ls -la src/hooks | head -12 came back verbose |
It has a pipe. rtk rewrite returns nothing for it. Not rewritable, so not a hook failure. |
Across the whole estate, 7 days, 582 top-level transcripts:
bash calls 16,493
rewritable 2,174 (13.2%)
rewritten 2,101 hit rate on rewritable 96.6%
of the 156 rewritable calls without a rewrite:
148 never executed at all (no PreToolUse attachments: interrupted or cancelled)
4 a hook errored
3 hooks ran, rtk produced nothing (multi-line commands, 22 Aug)
-> on calls that actually ran, about 99.7%
So the honest adoption number is not a hook problem. Only 13% of Bash calls on this machine are shapes RTK can rewrite at all. That is the real finding, and it has a cause.
| Shape | calls | share | rewritable | rewritten |
|---|---|---|---|---|
heredoc (cat > x.sh <<'EOF') | 7,547 | 45.8% | 0 | 13 |
| pipe | 6,150 | 37.3% | 1,372 | 1,351 |
| simple | 999 | 6.1% | 400 | 329 |
| chain | 965 | 5.9% | 402 | 368 |
| run script file | 622 | 3.8% | 0 | 24 |
| inline python | 210 | 1.3% | 0 | 16 |
Top-level session transcripts only; subagent transcripts are not included.
A few "rewritten" counts exceed "rewritable" because the shape classifier and
rtk rewrite disagree at the margins.
Nearly half of all commands are heredoc script files, and
rtk rewrite cannot see inside a heredoc. That shape is not an accident. This
machine carries a global rule that says write long, piped, or multi-stage commands to a
script file and run that, and a display-lint hook that nudges the same thing
on every prompt, for a real reason: terminal line-wrap splits flags from arguments. The rule
is doing its job. It is also, silently, the single largest reason RTK touches 13% of commands
instead of 50%. Two of my own safeguards were fighting each other, and neither could see the
other.
That is a trade-off to decide with the numbers in view, not a bug to fix. It was
invisible before because every instrument I reached for first, the buffered counter, the
output shape, rtk discover, was answering a different question than the one I
asked.
For the record, the two wrong diagnoses and what refuted each: (1) the bare
rtk hook claude registration introduced on 22 Aug (commit 5309ba0)
broke it: refuted by daily volume, 261 commands/day before vs 241 after with the peak day
(928) under the bare form; (2) platform's 27 project-level PreToolUse groups
shadow the global hook: refuted by rtk gain --project, platform has the
highest adoption on the machine at 17,540 commands and 59.4%. And the instrument that
would have prevented all of it, rtk discover, reports 0.0% adoption by
construction: transcripts store the model's original command, never the rewritten one, so
it cannot see a hook rewrite even when one happened on every call.
One more, found after the restart. I had repointed the registration at a wrapper script
and called it harmless hardening. It was not harmless: the wrapper delegated to
rtk rewrite, and rtk rewrite ignores RTK_HOOK_AUDIT
entirely. Only rtk hook claude writes the audit log. So after the restart the
hook was demonstrably rewriting (ls -la came back in rtk's compact form) while
rtk hook-audit still reported "No audit log found". The instrument I had just
enabled was disabled by the change I made alongside it, and I only caught it because I
checked the log instead of assuming it. The wrapper now execs rtk hook claude,
keeps the script-path registration, and writes the log. Verified end to end.