CLAUDE LABEN
CLI — Claude Code v2.1.261 が9月4日に出ました。全67変更のうち46件が修正で、CLI 側は入力処理とバックグラウンド実行の不具合が中心ですSKILLS — 新しい /skill-doctor が、読み込み済みスキルのうち未使用のものと、それぞれが毎ターン食っている文脈量を一覧にします。片づけの起点として素直に便利でしたCOST — 実運用環境の実測では、スキル一覧だけで毎ターン約13,800トークン。うち84件が一度も呼ばれておらず、同名プラグインの二重有効化による重複が全体の41%を占めていましたLIMIT — bashOutputMaxChars と taskOutputMaxChars が加わり、コマンド出力とバックグラウンド出力をファイル退避せずインラインで渡せる量を最大128K文字まで引き上げられますBREAKING — プロンプトの単語編集キーが Bash 準拠になり、keybindingFlavor は効かなくなりました。auto モードでは、図表レンダラURLへの埋め込みリンクがアップロード扱いになりますSAFEGUARDS — 9月1日に Enterprise Frontier Safeguards が発表されました。監視に使う活動データを Anthropic 側ではなく顧客が持つクラウドに置く設計で、追加課金はないとされていますCLI — Claude Code v2.1.261 が9月4日に出ました。全67変更のうち46件が修正で、CLI 側は入力処理とバックグラウンド実行の不具合が中心ですSKILLS — 新しい /skill-doctor が、読み込み済みスキルのうち未使用のものと、それぞれが毎ターン食っている文脈量を一覧にします。片づけの起点として素直に便利でしたCOST — 実運用環境の実測では、スキル一覧だけで毎ターン約13,800トークン。うち84件が一度も呼ばれておらず、同名プラグインの二重有効化による重複が全体の41%を占めていましたLIMIT — bashOutputMaxChars と taskOutputMaxChars が加わり、コマンド出力とバックグラウンド出力をファイル退避せずインラインで渡せる量を最大128K文字まで引き上げられますBREAKING — プロンプトの単語編集キーが Bash 準拠になり、keybindingFlavor は効かなくなりました。auto モードでは、図表レンダラURLへの埋め込みリンクがアップロード扱いになりますSAFEGUARDS — 9月1日に Enterprise Frontier Safeguards が発表されました。監視に使う活動データを Anthropic 側ではなく顧客が持つクラウドに置く設計で、追加課金はないとされています
記事一覧/Claude Code
Claude Code/2026-09-06初級

スキルを数えたら42本ありました。うち4本は中身が『移動しました』だけでした

Claude Code v2.1.261 で入った /skill-doctor を入り口に、自分のスキル棚を実際に数えてみました。毎ターン乗るのは説明の1行だけという構造と、名前の重複を素朴な awk で探すと別のスキルまで拾ってしまう落とし穴を、手元で動かした小さなスクリプトとともに書き残します。

Claude Code250Agent Skills3プラグイン6文脈設計2個人開発126

朝いちばんに、壁紙アプリの素材を仕分けるスキルを直そうとして一覧を開きました。上から目で追っていって、途中で手が止まりました。行が思ったより多いのです。

数えたら42本ありました。半分以上について、最後にいつ呼んだのかを思い出せませんでした。

入れた記憶はあります。どれも入れた日には必要でした。ただ、外す日というのは自分から訪れてくれません。棚は増える方向にしか動かないのだと、その朝にようやく認めました。

Claude Code v2.1.261(9月4日)に /skill-doctor が入りました。読み込んでいるスキルのうち、どれが使われておらず、どれだけ文脈を食べているかを一覧にしてくれるコマンドです。せっかくなので、自分の棚を先に数えてから向き合うことにしました。

毎ターン乗るのは、説明の1行だけです

先に構造の話をお伝えします。ここを取り違えると、数字の読み方がまるごとずれてしまうからです。

スキルが読み込まれているとき、毎ターン文脈に乗っているのは SKILL.md の本体ではありません。frontmatter に書いた namedescription、つまり「このスキルは何をするものか」の説明にあたる部分です。本体が読まれるのは、そのスキルが実際に呼ばれたときだけになります。

言い換えますと、一度も呼んでいないスキルでも、一覧に載っているというだけで説明の分は毎ターン支払っている、という構図です。「使っていないから無料」ではありません。

/skill-doctor が出す表は6つの列で構成されています。

意味
skillスキル名
sourceどこから来ているか(ユーザー/プラグイン/マーケットプレイス)
context説明1行分として毎ターン乗っている量
7d tokens直近7日で実際に消費した量
uses呼ばれた回数
last used最後に呼ばれた日時

並びは last used 順で、一度も呼ばれていない never が先頭に来ます。開いた瞬間に、いちばん見たくない行から目に入る設計になっています。

自分の棚を、実際に数えてみました

コマンドの結果を待つ前に、ファイルの側から数えられる分だけ数えました。フォルダを走査して、frontmatter の description が何文字あるかを足すだけの小さなスクリプトです。

import os, re, sys
 
root = sys.argv[1] if len(sys.argv) > 1 else "."
rows = []
for name in sorted(os.listdir(root)):
    path = os.path.join(root, name, "SKILL.md")
    if not os.path.isfile(path):
        continue
    text = open(path, encoding="utf-8", errors="replace").read()
    m = re.match(r"^---\n(.*?)\n---\n", text, re.S)
    desc = ""
    if m:
        d = re.search(r"^description:\s*(.*(?:\n[ \t]+.*)*)$", m.group(1), re.M)
        if d:
            desc = re.sub(r"\s+", " ", d.group(1).strip().strip("\"'"))
    rows.append((name, m is not None, len(desc), len(text), len(text.splitlines())))
 
with_fm = [r for r in rows if r[1]]
without  = [r for r in rows if not r[1]]
desc_total = sum(r[2] for r in with_fm)
body_total = sum(r[3] for r in rows)
 
print(f"SKILL.md のあるフォルダ : {len(rows)}")
print(f"frontmatter あり        : {len(with_fm)}")
print(f"frontmatter なし        : {len(without)}")
print(f"説明行の合計            : {desc_total:,} 文字 (平均 {desc_total // max(len(with_fm),1)})")
print(f"本体の合計              : {body_total:,} 文字 / {sum(r[4] for r in rows):,} 行")
print(f"説明行が占める割合      : {desc_total / body_total * 100:.2f} %")
print("説明行の長い順 上位3件  :")
for r in sorted(with_fm, key=lambda x: -x[2])[:3]:
    print(f"  {r[0]:<32} {r[2]:>4} 文字")

手元のスキルフォルダに向けた結果です。

SKILL.md のあるフォルダ : 42
frontmatter あり        : 38
frontmatter なし        : 4
説明行の合計            : 11,752 文字 (平均 309)
本体の合計              : 332,292 文字 / 8,931 行
説明行が占める割合      : 3.54 %
説明行の長い順 上位3件  :
  claude-api                        744 文字
  ai-seo                            698 文字
  seo-audit                         686 文字

本体は33万文字あるのに、毎ターン乗るのはそのうち 3.54% にあたる1万2千文字弱でした。この比率を見て、少し安心しました。棚が重いのは事実でも、重さのほとんどは呼んだときにだけ発生しているのです。

同時に、平均309文字という数字は軽くありません。説明が744文字あるスキルと79文字のスキルが同じ棚に並んでいて、その差は9倍を超えていました。説明を短く書き直すだけで減らせる分が、まだ残っているということになります。

4本は、移転を告げる紙だけが残っていました

いちばん効いたのは、frontmatter が無いフォルダが4本あった、という行でした。

中を開いたら、どれも「このファイルは移動しました」と新しい置き場所を書いただけの短い文書でした。前にスキルの置き場を整理したときの案内で、移した側の作業は終わっているのに、案内の紙だけが棚に残っていたのです。移した日には、その紙が要ると思っていました。

こういうものは、名前を見ているかぎり気づけません。名前は生きているままだからです。中身を開いて初めて、もう役目が終わっていると分かります。

棚に置いた数ではなく、手が伸びた数を数えます。 一覧の行数は、自分が使っているものの数ではありませんでした。この一文を、しばらく作業机の近くに置いておこうと思っています。

never を「不要」と読み替えないようにしています

ここで急ぎたくなるのですが、一度立ち止まる必要があります。

last usednever であることは、「この端末の記録上まだ呼ばれていない」という意味です。入れたばかりのスキルも never になりますし、年に数回の作業でしか呼ばないスキルも never になります。表示された時点では削除の候補であって、不要が確定したわけではないのです。

私の42本にも、四半期に一度だけ使うものが混ざっていました。これを勢いで消してしまうと、必要になった日に「あのとき消したもの」を思い出すところから始めることになります。

もう一つ、混ぜないようにしている話があります。未使用のスキルを減らすと応答の品質や速度が上がるのか、という点については、公式の情報に書かれていません。文脈のコストの話は文脈のコストの話として書き、品質の話とは別に扱うほうが誠実だと感じています。減ったのは支払いであって、腕前ではありません。

同じ名前が二つの棚から来ていないか

もう一つ確かめる価値があるのが、同じプラグインを二つのマーケットプレイスから有効にしていないか、という点です。名前が同じでも出どころが違えば別々に読み込まれますから、スキルの行が丸ごと二重になります。

/skill-doctor の出力をファイルへ落として、名前が重複している行を探すのが手早い方法です。ただ、素朴に一列目だけを取ると、空白の入った名前で足をすくわれます。手元で試したものを、そのまま置きます。

# 検証用に、名前へ空白を含む行を混ぜた表を作ります
cat > /tmp/sd.txt <<'TABLE'
skill                     source                    context  7d tokens  uses  last used
brand voice               marketplace-a             300      0          0     never
brand guidelines          user                      280      0          0     never
seo-audit                 user                      686      3120       4     2 days ago
seo-audit                 claude-plugins-official   686      0          0     never
TABLE
 
awk 'NF>3 {print $1}' /tmp/sd.txt | sort | uniq -d

結果はこうなりました。

brand
seo-audit

seo-audit は当たりです。しかし brand は外れでした。brand voicebrand guidelines は別のスキルなのに、一列目だけを見ると先頭の語が揃ってしまい、重複として報告されてしまったのです。名前に空白が入るスキルは珍しくありませんから、この誤検出は普通に起こります。

名前の列を「2つ以上の空白が現れるまで」で切ると、この取り違えは消えます。

awk 'NR>1 {
  if (match($0, /  +/)) {
    n = substr($0, 1, RSTART - 1)
    c[n]++
  }
} END {
  for (k in c) if (c[k] > 1) printf "%s\tx%d\n", k, c[k]
}' /tmp/sd.txt | sort
seo-audit	x2

NR>1 で見出し行を落としているのは、skill という語が名前として数えられてしまうのを避けるためです。素朴な版では、見出しも1件として数に入っていました。

出どころそのものを確かめたい場合は、設定ファイルの側から見ます。enabledPlugins は配列の形と辞書の形の両方を見かけますので、どちらでも通るようにしてあります。

import json, sys, collections
 
path = sys.argv[1] if len(sys.argv) > 1 else "settings.json"
try:
    data = json.load(open(path, encoding="utf-8"))
except FileNotFoundError:
    print(f"設定が見つかりません: {path}")
    sys.exit(0)
except json.JSONDecodeError as e:
    print(f"JSON を読めません: {path} ({e})")
    sys.exit(2)
 
raw = data.get("enabledPlugins")
pairs = []
if isinstance(raw, list):
    for entry in raw:
        name, _, market = str(entry).partition("@")
        pairs.append((name, market or "(marketplace 不明)"))
elif isinstance(raw, dict):
    for market, names in raw.items():
        for name in names or []:
            pairs.append((str(name), market))
else:
    print("enabledPlugins が配列でも辞書でもありません。形を先に確認してください。")
    sys.exit(2)
 
by_name = collections.defaultdict(list)
for name, market in pairs:
    by_name[name].append(market)
 
dups = {n: m for n, m in by_name.items() if len(m) > 1}
print(f"有効プラグイン {len(pairs)} 件 / 名前 {len(by_name)} 種")
for name in sorted(dups):
    print("  重複: " + name + " <- " + " / ".join(sorted(dups[name])))
sys.exit(1 if dups else 0)

配列の形と辞書の形、それぞれの設定を通した結果です。どちらでも同じ答えが返りました。

有効プラグイン 5 件 / 名前 3 種
  重複: aws-core <- agent-toolkit-for-aws / claude-plugins-official
  重複: frontend-design <- claude-plugins-official / my-marketplace

終了コードを 1 にしてあるのは、あとで朝の点検スクリプトに並べるためです。ファイルが無いときは 0 で静かに抜け、JSON が壊れているときだけ 2 を返します。無いことと壊れていることは、別の扱いにしておきたいのです。設定ファイルが無言で効かないまま放置される話は、settings.json のキー名を1文字間違えても、Claude Code は何も言わずに無視しますにも書きました。

明日の朝に、最初の一手

やることを一つだけに絞ります。/skill-doctor を一度だけ走らせて、last usednever の行が何本あるかを数えてください。数えるだけで、その場では消さないでください。

一週間置いてもう一度走らせると、そのあいだに一度でも呼ばれたスキルが never から外れます。二回目でも never のまま残ったものが、はじめて外す候補になります。私はこの二段構えにしてから、消して後悔することがなくなりました。

説明1行あたりの重さをもっと細かく詰めたい方には、起動しただけで1万トークン消えるスキルを、大きさではなく到達率で切り分けるで、節ごとに測って切り分けた実測を残しています。どのスキルを日常に残すかという手前の判断は、Claude Code Skills を毎日の開発に組み込むときに、私が見ている 5 つの選定軸のほうにまとめました。

棚を数えるのは気の重い作業でした。それでも、42という数字を見たあとのほうが、道具との距離が近くなった気がしています。最後までお付き合いいただき、ありがとうございました。

シェア

お読みいただきありがとうございます

Claude Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥2,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

Claude Code2026-08-22
Claude Code の headersHelper に移したら、プロジェクト配下のカタログだけ認証が通らなくなりました
自前のプラグインカタログを headersHelper へ移す途中で、ユーザースコープでは動くヘルパーがプロジェクト配下だけ落ちました。原因は認証情報の非継承です。動くヘルパー2種と実測した実行コスト、無人実行での注意点をまとめました。
Claude Code2026-08-20
起動しただけで1万トークン消えるスキルを、大きさではなく到達率で切り分ける
自分用の運用スキルが、呼び出しただけで約1万トークンを消費していました。節ごとにトークンを測り、最大の節ほど切り出してはいけない理由と、到達率で分けたときの実測値を、監査スクリプトつきでまとめます。
Claude Code2026-09-04
Claude Code に project.pbxproj だけは直接触らせていません
Xcode のプロジェクトファイルは、開けなくなる壊れ方より開けてしまう壊れ方のほうが高くつきました。直接編集をやめてスクリプト経由に寄せるまでに測ったことと、いま引いている線を書き残します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →