[{"data":1,"prerenderedAt":1422},["ShallowReactive",2],{"blog-\u002Fblog\u002Fclaude-code-token-analysis":3,"blog-siblings-\u002Fblog\u002Fclaude-code-token-analysis":1417},{"id":4,"title":5,"body":6,"category":1401,"date":1402,"description":1403,"draft":1404,"extension":1405,"meta":1406,"navigation":103,"path":1407,"seo":1408,"source":1409,"stem":1410,"tags":1411,"__hash__":1416},"blog\u002Fblog\u002Fclaude-code-token-analysis.md","我分析了 99 个会话、76MB 日志，终于搞懂 Claude Code 的 token 到底烧在哪",{"type":7,"value":8,"toc":1383},"minimark",[9,13,25,28,33,36,42,45,50,56,59,70,77,360,373,376,382,385,387,391,402,483,486,540,545,565,572,575,585,587,591,596,603,606,617,630,633,656,674,676,680,691,716,722,724,728,731,805,808,810,814,820,824,827,833,836,840,843,941,947,958,990,1008,1054,1076,1080,1083,1098,1116,1118,1122,1131,1169,1171,1175,1257,1271,1273,1277,1280,1361,1363,1366,1369,1376,1379],[10,11,5],"h1",{"id":12},"我分析了-99-个会话76mb-日志终于搞懂-claude-code-的-token-到底烧在哪",[14,15,16],"blockquote",{},[17,18,19,20,24],"p",{},"省 token 的关键，居然",[21,22,23],"strong",{},"不是\"少说话\"","。",[17,26,27],{},"如果你也在用 Claude Code，大概率有过这种体感：活儿是真干得漂亮，但 token 也是真烧得心疼。于是你开始凭感觉优化——让它少输出点、回答简短点、少啰嗦……",[17,29,30],{},[21,31,32],{},"然后发现并没有什么用。",[17,34,35],{},"这篇文章记录了我一次完整的\"数据驱动\"优化过程：不拍脑袋，而是把本地 99 个会话、76MB 的对话日志捞出来做量化分析，找到真正的烧钱黑洞，再动手优化，最后把经验固化成规则。全程有脚本、有数据、有实操、有结果，你可以照着复刻到自己的环境。",[17,37,38,39],{},"先剧透最反直觉的结论：",[21,40,41],{},"在我的数据里，输出（output）只占总成本的约 12%，而一个你几乎从没注意过的东西，占了约 75%。",[43,44],"hr",{},[46,47,49],"h2",{"id":48},"一别凭感觉先让数据说话","一、别凭感觉，先让数据说话",[17,51,52,53,24],{},"优化的第一原则：",[21,54,55],{},"没有测量就没有优化",[17,57,58],{},"Claude Code 会把每个会话的完整记录（含每次请求的 token 用量）以 JSONL 格式存在本地。路径长这样：",[60,61,66],"pre",{"className":62,"code":64,"language":65},[63],"language-text","C:\\Users\\\u003C你>\\.claude\\projects\\\u003C项目名>\\*.jsonl\n","text",[67,68,64],"code",{"__ignoreMap":69},"",[17,71,72,73,76],{},"先看看规模——一个 Python 脚本就够了（",[21,74,75],{},"这段脚本你可以直接拿去分析自己的数据","）：",[60,78,82],{"className":79,"code":80,"language":81,"meta":69,"style":69},"language-python shiki shiki-themes github-light github-dark","import os, glob, json\nfrom collections import Counter\n\nd = r'C:\\Users\\\u003C你>\\.claude\\projects\\\u003C项目名>'\nfiles = sorted(glob.glob(os.path.join(d, '*.jsonl')), key=os.path.getmtime)[-15:]  # 最近15个会话\n\nusage = Counter()          # token 结构\ntools = Counter()          # 工具调用次数\ntool_errors = 0            # 工具失败次数\nmodels = Counter()         # 模型分布\nread_files = Counter()     # 被反复读取的文件\nread_full = read_partial = 0\n\nfor f in files:\n    for line in open(f, encoding='utf-8', errors='replace'):\n        try: rec = json.loads(line)\n        except: continue\n        m = rec.get('message', {})\n        if rec.get('type') == 'assistant':\n            u = m.get('usage', {})\n            usage['input']        += u.get('input_tokens', 0)\n            usage['cache_read']   += u.get('cache_read_input_tokens', 0)\n            usage['cache_create'] += u.get('cache_creation_input_tokens', 0)\n            usage['output']       += u.get('output_tokens', 0)\n            models[m.get('model', '?')] += 1\n            for c in (m.get('content') or []):\n                if isinstance(c, dict) and c.get('type') == 'tool_use':\n                    tools[c.get('name', '?')] += 1\n                    if c.get('name') == 'Read':\n                        inp = c.get('input', {})\n                        read_files[os.path.basename(str(inp.get('file_path','')))] += 1\n                        if 'limit' in inp or 'offset' in inp: read_partial += 1\n                        else: read_full += 1\n\ntotal_in = usage['input'] + usage['cache_read'] + usage['cache_create']\nprint('=== Token 结构 ===')\nfor k, v in usage.items():\n    print(f'  {k:14s} {v\u002F1e6:7.1f}M')\nprint(f'  缓存命中率: {usage[\"cache_read\"]\u002Fmax(total_in,1)*100:.0f}%')\nprint('=== 工具调用 Top ===')\nfor t, n in tools.most_common(8): print(f'  {t:10s} {n}')\nprint(f'Read 全文\u002F部分: {read_full}\u002F{read_partial}')\nprint('=== 模型分布 ===')\nfor mdl, n in models.most_common(): print(f'  {mdl:32s} {n}')\nprint('=== 被反复 Read 的文件 ===')\nfor fn, n in read_files.most_common(6): print(f'  {fn:28s} {n}次')\n","python",[67,83,84,92,98,105,111,117,122,128,134,140,146,152,158,163,169,175,181,187,193,199,205,211,217,223,229,235,241,247,253,259,265,271,277,283,288,294,300,306,312,318,324,330,336,342,348,354],{"__ignoreMap":69},[85,86,89],"span",{"class":87,"line":88},"line",1,[85,90,91],{},"import os, glob, json\n",[85,93,95],{"class":87,"line":94},2,[85,96,97],{},"from collections import Counter\n",[85,99,101],{"class":87,"line":100},3,[85,102,104],{"emptyLinePlaceholder":103},true,"\n",[85,106,108],{"class":87,"line":107},4,[85,109,110],{},"d = r'C:\\Users\\\u003C你>\\.claude\\projects\\\u003C项目名>'\n",[85,112,114],{"class":87,"line":113},5,[85,115,116],{},"files = sorted(glob.glob(os.path.join(d, '*.jsonl')), key=os.path.getmtime)[-15:]  # 最近15个会话\n",[85,118,120],{"class":87,"line":119},6,[85,121,104],{"emptyLinePlaceholder":103},[85,123,125],{"class":87,"line":124},7,[85,126,127],{},"usage = Counter()          # token 结构\n",[85,129,131],{"class":87,"line":130},8,[85,132,133],{},"tools = Counter()          # 工具调用次数\n",[85,135,137],{"class":87,"line":136},9,[85,138,139],{},"tool_errors = 0            # 工具失败次数\n",[85,141,143],{"class":87,"line":142},10,[85,144,145],{},"models = Counter()         # 模型分布\n",[85,147,149],{"class":87,"line":148},11,[85,150,151],{},"read_files = Counter()     # 被反复读取的文件\n",[85,153,155],{"class":87,"line":154},12,[85,156,157],{},"read_full = read_partial = 0\n",[85,159,161],{"class":87,"line":160},13,[85,162,104],{"emptyLinePlaceholder":103},[85,164,166],{"class":87,"line":165},14,[85,167,168],{},"for f in files:\n",[85,170,172],{"class":87,"line":171},15,[85,173,174],{},"    for line in open(f, encoding='utf-8', errors='replace'):\n",[85,176,178],{"class":87,"line":177},16,[85,179,180],{},"        try: rec = json.loads(line)\n",[85,182,184],{"class":87,"line":183},17,[85,185,186],{},"        except: continue\n",[85,188,190],{"class":87,"line":189},18,[85,191,192],{},"        m = rec.get('message', {})\n",[85,194,196],{"class":87,"line":195},19,[85,197,198],{},"        if rec.get('type') == 'assistant':\n",[85,200,202],{"class":87,"line":201},20,[85,203,204],{},"            u = m.get('usage', {})\n",[85,206,208],{"class":87,"line":207},21,[85,209,210],{},"            usage['input']        += u.get('input_tokens', 0)\n",[85,212,214],{"class":87,"line":213},22,[85,215,216],{},"            usage['cache_read']   += u.get('cache_read_input_tokens', 0)\n",[85,218,220],{"class":87,"line":219},23,[85,221,222],{},"            usage['cache_create'] += u.get('cache_creation_input_tokens', 0)\n",[85,224,226],{"class":87,"line":225},24,[85,227,228],{},"            usage['output']       += u.get('output_tokens', 0)\n",[85,230,232],{"class":87,"line":231},25,[85,233,234],{},"            models[m.get('model', '?')] += 1\n",[85,236,238],{"class":87,"line":237},26,[85,239,240],{},"            for c in (m.get('content') or []):\n",[85,242,244],{"class":87,"line":243},27,[85,245,246],{},"                if isinstance(c, dict) and c.get('type') == 'tool_use':\n",[85,248,250],{"class":87,"line":249},28,[85,251,252],{},"                    tools[c.get('name', '?')] += 1\n",[85,254,256],{"class":87,"line":255},29,[85,257,258],{},"                    if c.get('name') == 'Read':\n",[85,260,262],{"class":87,"line":261},30,[85,263,264],{},"                        inp = c.get('input', {})\n",[85,266,268],{"class":87,"line":267},31,[85,269,270],{},"                        read_files[os.path.basename(str(inp.get('file_path','')))] += 1\n",[85,272,274],{"class":87,"line":273},32,[85,275,276],{},"                        if 'limit' in inp or 'offset' in inp: read_partial += 1\n",[85,278,280],{"class":87,"line":279},33,[85,281,282],{},"                        else: read_full += 1\n",[85,284,286],{"class":87,"line":285},34,[85,287,104],{"emptyLinePlaceholder":103},[85,289,291],{"class":87,"line":290},35,[85,292,293],{},"total_in = usage['input'] + usage['cache_read'] + usage['cache_create']\n",[85,295,297],{"class":87,"line":296},36,[85,298,299],{},"print('=== Token 结构 ===')\n",[85,301,303],{"class":87,"line":302},37,[85,304,305],{},"for k, v in usage.items():\n",[85,307,309],{"class":87,"line":308},38,[85,310,311],{},"    print(f'  {k:14s} {v\u002F1e6:7.1f}M')\n",[85,313,315],{"class":87,"line":314},39,[85,316,317],{},"print(f'  缓存命中率: {usage[\"cache_read\"]\u002Fmax(total_in,1)*100:.0f}%')\n",[85,319,321],{"class":87,"line":320},40,[85,322,323],{},"print('=== 工具调用 Top ===')\n",[85,325,327],{"class":87,"line":326},41,[85,328,329],{},"for t, n in tools.most_common(8): print(f'  {t:10s} {n}')\n",[85,331,333],{"class":87,"line":332},42,[85,334,335],{},"print(f'Read 全文\u002F部分: {read_full}\u002F{read_partial}')\n",[85,337,339],{"class":87,"line":338},43,[85,340,341],{},"print('=== 模型分布 ===')\n",[85,343,345],{"class":87,"line":344},44,[85,346,347],{},"for mdl, n in models.most_common(): print(f'  {mdl:32s} {n}')\n",[85,349,351],{"class":87,"line":350},45,[85,352,353],{},"print('=== 被反复 Read 的文件 ===')\n",[85,355,357],{"class":87,"line":356},46,[85,358,359],{},"for fn, n in read_files.most_common(6): print(f'  {fn:28s} {n}次')\n",[14,361,362],{},[17,363,364,365,368,369,372],{},"💡 ",[21,366,367],{},"省 token 小技巧（元级别的）","：分析日志时",[21,370,371],{},"别把原始 JSONL 直接丢给 AI 读","——76MB 会瞬间撑爆上下文、烧掉一大笔。用脚本在本地聚合成几十行统计结果，再交给 AI 分析。这本身就是第一课。",[17,374,375],{},"跑出来的真实结果（最近 15 个会话累计）：",[60,377,380],{"className":378,"code":379,"language":65},[63],"=== Token 结构 ===\n  input            0.9M\n  cache_read     212.4M\n  cache_create   127.0M\n  output           5.2M\n  缓存命中率: 62%\n=== 工具调用 Top ===\n  Read       237\n  Edit       231\n  Bash       200\n  Grep        66\n  Write       34\n=== 模型分布 ===\n  claude-opus-4-8                  1126\n  claude-fable-5                    536\n  claude-haiku-4-5-20251001         353\n=== 被反复 Read 的文件 ===\n  EmbedChat.vue                17次\n  schema.ts                    11次\n  nodeCapabilities.ts          10次\n",[67,381,379],{"__ignoreMap":69},[17,383,384],{},"数据一摆出来，问题立刻就不一样了。",[43,386],{},[46,388,390],{"id":389},"二核弹级发现你以为的成本大头根本不是大头","二、核弹级发现：你以为的成本大头，根本不是大头",[17,392,393,394,397,398,401],{},"先把这四个数字换算成",[21,395,396],{},"真实成本占比","。关键在于 Claude 的 ",[21,399,400],{},"Prompt Caching（提示缓存）"," 定价系数各不相同：",[403,404,405,421],"table",{},[406,407,408],"thead",{},[409,410,411,415,418],"tr",{},[412,413,414],"th",{},"Token 类型",[412,416,417],{},"定价系数（相对基础 input）",[412,419,420],{},"含义",[422,423,424,438,454,470],"tbody",{},[409,425,426,432,435],{},[427,428,429],"td",{},[67,430,431],{},"input",[427,433,434],{},"1×",[427,436,437],{},"全新的、没缓存的输入",[409,439,440,446,451],{},[427,441,442,445],{},[67,443,444],{},"cache_read","（读缓存）",[427,447,448],{},[21,449,450],{},"0.1×",[427,452,453],{},"命中缓存，超便宜",[409,455,456,462,467],{},[427,457,458,461],{},[67,459,460],{},"cache_create","（写缓存）",[427,463,464],{},[21,465,466],{},"1.25×",[427,468,469],{},"把内容写进缓存，有溢价",[409,471,472,477,480],{},[427,473,474],{},[67,475,476],{},"output",[427,478,479],{},"~5×",[427,481,482],{},"模型的输出",[17,484,485],{},"按这组系数给上面的 token 量加权，得到成本结构：",[403,487,488,498],{},[406,489,490],{},[409,491,492,495],{},[412,493,494],{},"成本项",[412,496,497],{},"占比（加权估算）",[422,499,500,510,520,530],{},[409,501,502,507],{},[427,503,504,506],{},[67,505,460],{}," 写缓存",[427,508,509],{},"约 75%",[409,511,512,517],{},[427,513,514,516],{},[67,515,476],{}," 输出",[427,518,519],{},"约 13%",[409,521,522,527],{},[427,523,524,526],{},[67,525,444],{}," 读缓存",[427,528,529],{},"约 11%",[409,531,532,537],{},[427,533,534,536],{},[67,535,431],{}," 全新输入",[427,538,539],{},"约 1%",[17,541,542],{},[21,543,544],{},"看清楚了吗？",[546,547,548,556],"ul",{},[549,550,551,552,555],"li",{},"你拼命想压缩的 ",[21,553,554],{},"output（输出），只占约 12–13%","；",[549,557,558,559,564],{},"而 ",[21,560,561,563],{},[67,562,460],{},"（写缓存）独占约 75%","——这才是真正的碎钞机。",[14,566,567],{},[17,568,569],{},[21,570,571],{},"省 token 的本质，不是让模型少说话，而是减少\"缓存重建\"。",[17,573,574],{},"这就是为什么凭感觉\"让它回答简短点\"几乎没用——你在优化那 12%，却对着 75% 的黑洞视而不见。",[17,576,577,578,584],{},"那么问题来了：",[21,579,580,581,583],{},"什么会疯狂触发 ",[67,582,460],{},"？"," 我从数据里挖出了三个元凶。",[43,586],{},[46,588,590],{"id":589},"三三大烧钱黑洞","三、三大烧钱黑洞",[592,593,595],"h3",{"id":594},"️-黑洞一会话中途切换模型","🕳️ 黑洞一：会话中途切换模型",[17,597,598,599,602],{},"看模型分布那组数据——",[21,600,601],{},"同一批会话里，opus、fable、haiku 三个模型混着用","（1126 \u002F 536 \u002F 353 条消息）。",[17,604,605],{},"这里有个很多人不知道的机制：",[14,607,608],{},[17,609,610],{},[21,611,612,613,616],{},"Prompt 缓存是和模型绑定的。你在会话中途每 ",[67,614,615],{},"\u002Fmodel"," 切一次，之前积累的全部上下文缓存，对新模型全部失效，必须从头重写一遍。",[17,618,619,620,626,627,629],{},"也就是说，一段几万 token 的上下文，如果你在会话里切了 3 次模型，最坏情况要付 ",[21,621,622,623,625],{},"3 次 ",[67,624,460],{}," 的写入费","。这正是 ",[67,628,460],{}," 高达 127M 的头号推手。",[17,631,632],{},"切一次模型，链条上发生的事：",[634,635,636,639,645,648,651],"ol",{},[549,637,638],{},"会话上下文已缓存 ✅",[549,640,641,642,644],{},"执行 ",[67,643,615],{}," 切换",[549,646,647],{},"缓存对新模型失效 ❌",[549,649,650],{},"整段上下文重新写缓存 💸",[549,652,653,655],{},[67,654,460],{}," 暴涨",[17,657,658,661,662,665,666,669,670,673],{},[21,659,660],{},"✅ 对策","：模型选择尽量在",[21,663,664],{},"会话开始前","定好；确实要切，就挑一个",[21,667,668],{},"自然断点","，切完顺手 ",[67,671,672],{},"\u002Fclear"," 或开新会话，别让旧上下文拖着重写。",[43,675],{},[592,677,679],{"id":678},"️-黑洞二臃肿的系统提示底座","🕳️ 黑洞二：臃肿的\"系统提示底座\"",[17,681,682,683,686,687,690],{},"每次会话，系统提示里都会注入一大坨固定内容：所有 Skill 的描述、启用插件的清单、全局与项目的 ",[67,684,685],{},"CLAUDE.md","……这坨东西每次缓存失效都要重新计费。而我的底座当时",[21,688,689],{},"肥得离谱","：",[546,692,693,700,707],{},[549,694,695,696,699],{},"全局装了 ",[21,697,698],{},"90+ 个 Skill","，每个的描述都往系统提示里塞；",[549,701,702,703,706],{},"多个插件\"",[21,704,705],{},"整包注入","\"——一个插件条目就带进十几个 Skill 的描述；",[549,708,709,710,712,713,24],{},"全局 ",[67,711,685],{}," 里，",[21,714,715],{},"同一套\"模型选择\u002F委派矩阵\"翻来覆去写了三遍",[17,717,718,719,721],{},"这坨底座越大，每次 ",[67,720,460],{}," 就越贵。",[43,723],{},[592,725,727],{"id":726},"️-黑洞三行为层的隐性浪费","🕳️ 黑洞三：行为层的隐性浪费",[17,729,730],{},"这个藏在工具调用里，最容易被忽略：",[403,732,733,746],{},[406,734,735],{},[409,736,737,740,743],{},[412,738,739],{},"浪费行为",[412,741,742],{},"数据实锤",[412,744,745],{},"为什么烧钱",[422,747,748,768,786],{},[409,749,750,756,765],{},[427,751,752,753],{},"大文件反复",[21,754,755],{},"全文读",[427,757,758,761,762],{},[67,759,760],{},"EmbedChat.vue"," 被整读 ",[21,763,764],{},"17 次",[427,766,767],{},"每次全读都把整个文件塞进上下文",[409,769,770,776,783],{},[427,771,772,773],{},"工具调用",[21,774,775],{},"失败重试",[427,777,778,779,782],{},"累计 ",[21,780,781],{},"38 次","失败",[427,784,785],{},"每次失败=多一轮重复上下文",[409,787,788,791,798],{},[427,789,790],{},"Read 全文 vs 局部",[427,792,793,794,797],{},"全文 ",[21,795,796],{},"138"," 次 \u002F 局部仅 99 次",[427,799,800,801,804],{},"全文读比 ",[67,802,803],{},"offset\u002Flimit"," 局部读贵得多",[17,806,807],{},"每一次\"整读一个 400 行的大文件\"，都是往上下文里灌了一大桶水，而这桶水会跟着后续每一次缓存重建反复计费。",[43,809],{},[46,811,813],{"id":812},"四动手优化有前后对比","四、动手优化（有前后对比）",[17,815,816,817],{},"找到黑洞，就可以精准下刀了。原则只有一条：",[21,818,819],{},"只砍冗余，绝不牺牲能力。",[592,821,823],{"id":822},"_41-给-claudemd-瘦身","4.1 给 CLAUDE.md 瘦身",[17,825,826],{},"把三段重复的\"模型\u002F委派矩阵\"合并成一张表，语义零丢失：",[60,828,831],{"className":829,"code":830,"language":65},[63],"全局 CLAUDE.md：169 行  ➜  131 行   （-22%）\n",[67,832,830],{"__ignoreMap":69},[17,834,835],{},"删掉的全是重复表述——增量信息一条没少，只是不再\"写三遍\"。",[592,837,839],{"id":838},"_42-skill-大清理90-28","4.2 Skill 大清理：90 ➜ 28",[17,841,842],{},"这是最狠的一刀。我把 90 个 Skill 按\"和我的实际工作（Vue 前端 + 文档）相关度\"分组，逐组清理：",[403,844,845,858],{},[406,846,847],{},[409,848,849,852,855],{},[412,850,851],{},"分组",[412,853,854],{},"数量",[412,856,857],{},"处理",[422,859,860,871,882,892,901,911,920,930],{},[409,861,862,865,868],{},[427,863,864],{},"与插件重复",[427,866,867],{},"16",[427,869,870],{},"删全局留插件版，零损失",[409,872,873,876,879],{},[427,874,875],{},"记忆系统系列",[427,877,878],{},"9",[427,880,881],{},"删除",[409,883,884,887,890],{},[427,885,886],{},"部署平台",[427,888,889],{},"4",[427,891,881],{},[409,893,894,897,899],{},[427,895,896],{},"SaaS 平台特定",[427,898,878],{},[427,900,881],{},[409,902,903,906,909],{},[427,904,905],{},"技术栈不匹配",[427,907,908],{},"3",[427,910,881],{},[409,912,913,916,918],{},[427,914,915],{},"杂项 \u002F 与 MCP 重复",[427,917,878],{},[427,919,881],{},[409,921,922,925,928],{},[427,923,924],{},"娱乐 \u002F 商业及其他",[427,926,927],{},"12",[427,929,881],{},[409,931,932,935,938],{},[427,933,934],{},"工作相关",[427,936,937],{},"28",[427,939,940],{},"✅ 保留",[17,942,943,944,24],{},"删除操作本身也有坑——这里插播一个",[21,945,946],{},"血泪教训",[17,948,949,950,953,954,957],{},"Claude Code 的 ",[67,951,952],{},"!"," 命令前缀在我的 Windows 机器上跑的是 ",[21,955,956],{},"Git Bash","，不是 PowerShell。我一开始想当然给了 PowerShell 语法：",[60,959,963],{"className":960,"code":961,"language":962,"meta":69,"style":69},"language-powershell shiki shiki-themes github-light github-dark","# ❌ 错误：Remove-Item 是 PowerShell 命令，Git Bash 不认；\n#         反斜杠 \\ 在 bash 里是转义符，路径会被吞掉\ncd $HOME\\.claude\\skills; Remove-Item -Recurse -Force ponytail,yeet\n# 报错：Remove-Item: command not found\n#       cd: \u002Fc\u002FUsers\u002Fxxx.claudeskills: No such file or directory\n","powershell",[67,964,965,970,975,980,985],{"__ignoreMap":69},[85,966,967],{"class":87,"line":88},[85,968,969],{},"# ❌ 错误：Remove-Item 是 PowerShell 命令，Git Bash 不认；\n",[85,971,972],{"class":87,"line":94},[85,973,974],{},"#         反斜杠 \\ 在 bash 里是转义符，路径会被吞掉\n",[85,976,977],{"class":87,"line":100},[85,978,979],{},"cd $HOME\\.claude\\skills; Remove-Item -Recurse -Force ponytail,yeet\n",[85,981,982],{"class":87,"line":107},[85,983,984],{},"# 报错：Remove-Item: command not found\n",[85,986,987],{"class":87,"line":113},[85,988,989],{},"#       cd: \u002Fc\u002FUsers\u002Fxxx.claudeskills: No such file or directory\n",[17,991,992,993,996,997,1000,1001,1004,1005,76],{},"正确姿势是 ",[21,994,995],{},"Git Bash 语法","（正斜杠 ",[67,998,999],{},"\u002F","、",[67,1002,1003],{},"~"," 家目录、空格分隔、",[67,1006,1007],{},"rm -rf",[60,1009,1013],{"className":1010,"code":1011,"language":1012,"meta":69,"style":69},"language-bash shiki shiki-themes github-light github-dark","# ✅ 正确\ncd ~\u002F.claude\u002Fskills && rm -rf ponytail ponytail-audit ponytail-review yeet\n","bash",[67,1014,1015,1021],{"__ignoreMap":69},[85,1016,1017],{"class":87,"line":88},[85,1018,1020],{"class":1019},"sJ8bj","# ✅ 正确\n",[85,1022,1023,1027,1031,1035,1039,1042,1045,1048,1051],{"class":87,"line":94},[85,1024,1026],{"class":1025},"sj4cs","cd",[85,1028,1030],{"class":1029},"sZZnC"," ~\u002F.claude\u002Fskills",[85,1032,1034],{"class":1033},"sVt8B"," && ",[85,1036,1038],{"class":1037},"sScJk","rm",[85,1040,1041],{"class":1025}," -rf",[85,1043,1044],{"class":1029}," ponytail",[85,1046,1047],{"class":1029}," ponytail-audit",[85,1049,1050],{"class":1029}," ponytail-review",[85,1052,1053],{"class":1029}," yeet\n",[14,1055,1056],{},[17,1057,1058,1059,690,1062,1064,1065,1068,1069,1072,1073,1075],{},"⚠️ ",[21,1060,1061],{},"安全提示",[67,1063,1007],{}," 删的是全局配置，",[21,1066,1067],{},"不可逆","。删前先用只读命令 ",[67,1070,1071],{},"ls"," 确认目标，删后再 ",[67,1074,1071],{}," 验证清零。",[592,1077,1079],{"id":1078},"_43-插件层审查真正的注入大头","4.3 插件层审查：真正的注入大头",[17,1081,1082],{},"清完 Skill 我才意识到一个更关键的点，也是本文我最想分享的洞察：",[14,1084,1085],{},[17,1086,1087,1090,1091,1094,1095,1097],{},[21,1088,1089],{},"注入成本 ≠ 目录数量。"," 那些启用中的插件（",[67,1092,1093],{},"enabledPlugins = True","）是\"",[21,1096,705],{},"\"——一个插件条目就带进十几个 Skill 的描述，比你手动删十几个散装 Skill 目录，影响还大。",[17,1099,1100,1101,1108,1109],{},"所以优化配置的正确顺序应该是：",[21,1102,1103,1104,1107],{},"先看 ",[67,1105,1106],{},"enabledPlugins"," 启用清单（大头），再清散装 Skill（小头）。"," 我据此关掉了用不上的插件，并保留了确实高频的（代码审查、文档处理等）——",[21,1110,1111,1112,1115],{},"关掉的是能力冗余，不是能力本身，随时能在 ",[67,1113,1114],{},"\u002Fplugin"," 里重新开。",[43,1117],{},[46,1119,1121],{"id":1120},"五把经验固化成肌肉记忆","五、把经验固化成\"肌肉记忆\"",[17,1123,1124,1125,1128,1129,76],{},"一次性优化会随时间腐化。真正的杀招是把结论",[21,1126,1127],{},"写进规则","，让它每次自动生效。我把这次的发现沉淀成了一份\"行为准则\"（写进记忆 \u002F ",[67,1130,685],{},[634,1132,1133,1146,1152,1158,1164],{},[549,1134,1135,1142,1143,555],{},[21,1136,1137,1138,1141],{},"大文件先 ",[67,1139,1140],{},"Grep"," 定位再局部读","，禁止习惯性全文 ",[67,1144,1145],{},"Read",[549,1147,1148,1151],{},[21,1149,1150],{},"Edit 失败一次，立刻精确重读再改","，禁止盲目重试第二次；",[549,1153,1154,1157],{},[21,1155,1156],{},"已定位的小改动主会话直接改","，不为省事去委派子代理（委派的上下文开销反而更大）；",[549,1159,1160,1163],{},[21,1161,1162],{},"会话中途切模型时主动提醒","：缓存会失效，建议自然断点切换；",[549,1165,1166,24],{},[21,1167,1168],{},"能用一次脚本聚合查询的，绝不用多轮读原始文件",[43,1170],{},[46,1172,1174],{"id":1173},"六成果总账","六、成果总账",[403,1176,1177,1193],{},[406,1178,1179],{},[409,1180,1181,1184,1187,1190],{},[412,1182,1183],{},"优化项",[412,1185,1186],{},"Before",[412,1188,1189],{},"After",[412,1191,1192],{},"效果",[422,1194,1195,1211,1227,1241],{},[409,1196,1197,1200,1203,1208],{},[427,1198,1199],{},"全局 CLAUDE.md",[427,1201,1202],{},"169 行",[427,1204,1205],{},[21,1206,1207],{},"131 行",[427,1209,1210],{},"去掉三段重复矩阵",[409,1212,1213,1216,1219,1224],{},[427,1214,1215],{},"全局 Skill",[427,1217,1218],{},"90 个",[427,1220,1221],{},[21,1222,1223],{},"28 个",[427,1225,1226],{},"砍掉 69%，零能力损失",[409,1228,1229,1232,1235,1238],{},[427,1230,1231],{},"插件层",[427,1233,1234],{},"全量启用",[427,1236,1237],{},"按需启用",[427,1239,1240],{},"掐掉整包注入大头",[409,1242,1243,1246,1249,1254],{},[427,1244,1245],{},"行为准则",[427,1247,1248],{},"无",[427,1250,1251],{},[21,1252,1253],{},"5 条固化",[427,1255,1256],{},"持续生效，防腐化",[17,1258,1259,1260,1266,1267,1270],{},"配合\"三大黑洞\"对策（不中途切模型、瘦底座、改行为），",[21,1261,1262,1263,1265],{},"系统提示底座与 ",[67,1264,460],{}," 的重建成本被显著压下来","，而 Claude Code 的实际能力",[21,1268,1269],{},"一点没减","——删的每一样，要么是重复注入，要么是和工作八竿子打不着的东西。",[43,1272],{},[46,1274,1276],{"id":1275},"七给你的可复用-checklist","七、给你的可复用 Checklist",[17,1278,1279],{},"想复刻的话，照这个清单走：",[546,1281,1284,1300,1312,1325,1336,1342,1351],{"className":1282},[1283],"contains-task-list",[549,1285,1288,1291,1292,1295,1296,1299],{"className":1286},[1287],"task-list-item",[431,1289],{"disabled":103,"type":1290},"checkbox"," 用文中的 ",[21,1293,1294],{},"Python 脚本","分析自己的 ",[67,1297,1298],{},"~\u002F.claude\u002Fprojects\u002F*\u002F*.jsonl","，先看清成本结构；",[549,1301,1303,1305,1306,1308,1309,555],{"className":1302},[1287],[431,1304],{"disabled":103,"type":1290}," 盯住 ",[67,1307,460],{}," 占比——",[21,1310,1311],{},"它才是大头，不是 output",[549,1313,1315,1317,1318,1321,1322,1324],{"className":1314},[1287],[431,1316],{"disabled":103,"type":1290}," 固定模型，",[21,1319,1320],{},"不在会话中途乱切","；要切就 ",[67,1323,672],{}," 开新局；",[549,1326,1328,1330,1331,1335],{"className":1327},[1287],[431,1329],{"disabled":103,"type":1290}," 先审 ",[21,1332,1333],{},[67,1334,1106],{},"（整包注入），再清散装 Skill；",[549,1337,1339,1341],{"className":1338},[1287],[431,1340],{"disabled":103,"type":1290}," 删掉和你技术栈无关的 Skill\u002F插件（部署、SaaS、异栈、娱乐类）；",[549,1343,1345,1347,1348,1350],{"className":1344},[1287],[431,1346],{"disabled":103,"type":1290}," 合并 ",[67,1349,685],{}," 里的重复段落；",[549,1352,1354,1356,1357,1360],{"className":1353},[1287],[431,1355],{"disabled":103,"type":1290}," 把优化结论",[21,1358,1359],{},"写成规则","，别指望下次还记得。",[43,1362],{},[46,1364,1365],{"id":1365},"写在最后",[17,1367,1368],{},"这次优化最大的收获，其实不是省了多少钱，而是那个思维转变：",[14,1370,1371],{},[17,1372,1373],{},[21,1374,1375],{},"凭感觉优化，你会一直对着\"输出\"这 12% 使劲；用数据说话，你才会看见\"缓存重建\"那 75% 的真黑洞。",[17,1377,1378],{},"工具再智能，也替代不了你\"先测量、再动手\"的工程习惯。希望这篇能帮你把 Claude Code 用得又爽又省。",[1380,1381,1382],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}",{"title":69,"searchDepth":100,"depth":100,"links":1384},[1385,1386,1387,1392,1397,1398,1399,1400],{"id":48,"depth":94,"text":49},{"id":389,"depth":94,"text":390},{"id":589,"depth":94,"text":590,"children":1388},[1389,1390,1391],{"id":594,"depth":100,"text":595},{"id":678,"depth":100,"text":679},{"id":726,"depth":100,"text":727},{"id":812,"depth":94,"text":813,"children":1393},[1394,1395,1396],{"id":822,"depth":100,"text":823},{"id":838,"depth":100,"text":839},{"id":1078,"depth":100,"text":1079},{"id":1120,"depth":94,"text":1121},{"id":1173,"depth":94,"text":1174},{"id":1275,"depth":94,"text":1276},{"id":1365,"depth":94,"text":1365},"ai-agent","2026-07-17","用脚本量化本地会话日志后发现，输出只占成本约 12%，缓存重建才是 75% 的大头。记录三大烧钱黑洞、对应优化与可复用清单。",false,"md",{},"\u002Fblog\u002Fclaude-code-token-analysis",{"title":5,"description":1403},null,"blog\u002Fclaude-code-token-analysis",[1412,1413,1414,1415],"claude-code","ai","performance","best-practice","Rw_ezfUmRY6gjLOGJOksOPRXNoqEBC5ZhkMXCImec8w",{"prev":1409,"next":1418},{"path":1419,"title":1420,"description":1421},"\u002Fblog\u002Fnvm-pnpm-notes","nvm 版本管理与 pnpm 对比笔记","解决 nvm list available 返回空的镜像配置问题，并对比 pnpm 与 npm 在依赖存储与安装速度上的差异。",1789635933370]