Claude Code の更新を追うメモに「新版は週に 5〜6 本くらい」と書く前に、一度だけ数えて確かめておくことにしました。感覚で書いた数字は、あとで自分の判断を静かにずらしてしまうからです。
そこで、公開履歴を数える小さなスクリプトを組みました。必要なのは python3 と、npm のレジストリに届くネットワークだけです。組み立ての順番と、動かして気づいた落とし穴を二つ、順に書き残します。個人開発の合間に Claude Code を使っている私にとって、更新の頻度は作業計画に直結する数字だからです。
先に、今日の数字をお伝えします
最初にお伝えしたいのは、公開間隔は「平均」ではなく「中央値と最大値」で見たほうが、実感に近いということです。今日の昼に動かした結果は次のとおりでした(UTC 03 時台の実行です)。
| ISO 週 | 公開本数 |
|---|---|
| 2026-W39 | 4 本 |
| 2026-W40 | 6 本 |
| 2026-W41 | 7 本 |
| 2026-W42 | 5 本 |
| 2026-W43 | 7 本 |
| 2026-W44(火曜時点) | 1 本 |
直近 60 回の公開間隔は、中央値が 23.2 時間、最大が 103.4 時間でした。つまり、ふだんは一日に一本のペースで、いちばん空いたときでも四日と少しです。「週に 5〜6 本」という見立ては、完結した W40 から W43 の 5〜7 本という範囲に、おおよそ収まっていました。
手順 1:レジストリから公開時刻を取り出します
npm のレジストリは、パッケージ名のパスにアクセスするだけで JSON を返します。その中の time というキーに、版番号ごとの公開時刻が入っています。
def fetch(pkg):
url = f"https://registry.npmjs.org/{pkg}"
with urllib.request.urlopen(url, timeout=30) as r:
return json.load(r)@anthropic-ai/claude-code のようにスコープ付きの名前も、そのまま URL に書けます。この JSON は、Claude Code のように 500 本以上の履歴を持つパッケージだと 1.5 MB ほどになります(今日の取得で 1,564,015 バイトでした)。毎分叩くような使い方は避けたほうがよさそうです。
手順 2:版の一覧から余計なものを除きます
time には、版番号のほかに created と modified という二つのキーが混ざっています。さらに、2.2.0-beta.1 のようなプレリリースも並びます。数えたいのは通常の公開だけですので、この二種類を落としてから、時刻順に並べ直します。
def stable_releases(doc):
out = []
for ver, stamp in doc["time"].items():
if ver in ("created", "modified") or "-" in ver:
continue
out.append((ver, datetime.fromisoformat(stamp.replace("Z", "+00:00"))))
return sorted(out, key=lambda x: x[1])関数名の stable は「安定版チャンネル」の意味ではなく、プレリリースを除いた、という意味で付けました。紛らわしいので、使い回す際は改名なさってください。チャンネルの遅れそのものを数える方法は、以前に安定版の Claude Code には、二度の既定モデル交代がまだ届いていませんで書いています。
手順 3:週ごとに数え、間隔の中央値を出します
週の区切りには ISO 週(%G-W%V)を使いました。年の変わり目に %Y と %W を組み合わせると、週番号が年をまたいでずれることがあるためです。
per_week = Counter(t.strftime("%G-W%V") for _, t in rel)
gaps = [(b[1] - a[1]).total_seconds() / 3600 for a, b in zip(rel, rel[1:])][-RECENT:]
print(f"中央値 {statistics.median(gaps):.1f} 時間 / 最大 {max(gaps):.1f} 時間")隣り合う公開の時刻差を zip(rel, rel[1:]) で作り、末尾の RECENT 個だけを取っています。平均ではなく中央値を使うのは、週末をまたいだ長い空白が一つ混ざるだけで、平均が引き上げられてしまうからです。
全体のスクリプトです
ここまでをまとめた全体が、次の 37 行です。python3 cadence.py で既定のパッケージを、python3 cadence.py lodash 20 のように引数を足せば別のパッケージを数えられます。
#!/usr/bin/env python3
"""npm の公開履歴から、週ごとの公開本数と公開間隔の中央値・最大値を数える。"""
import json, sys, statistics, urllib.request
from collections import Counter
from datetime import datetime, timedelta, timezone
PKG = sys.argv[1] if len(sys.argv) > 1 else "@anthropic-ai/claude-code"
RECENT = int(sys.argv[2]) if len(sys.argv) > 2 else 60
def fetch(pkg):
url = f"https://registry.npmjs.org/{pkg}"
with urllib.request.urlopen(url, timeout=30) as r:
return json.load(r)
def stable_releases(doc):
out = []
for ver, stamp in doc["time"].items():
if ver in ("created", "modified") or "-" in ver: # プレリリース (x.y.z-beta) は除く
continue
out.append((ver, datetime.fromisoformat(stamp.replace("Z", "+00:00"))))
return sorted(out, key=lambda x: x[1])
def main():
rel = stable_releases(fetch(PKG))
per_week = Counter(t.strftime("%G-W%V") for _, t in rel)
print(f"package={PKG} total={len(rel)}")
now = datetime.now(timezone.utc)
for back in range(5, -1, -1): # 0 本の週も落とさず、直近 6 週を連続で出す
week = (now - timedelta(weeks=back)).strftime("%G-W%V")
print(f" {week}: {per_week.get(week, 0)} 本")
gaps = [(b[1] - a[1]).total_seconds() / 3600 for a, b in zip(rel, rel[1:])][-RECENT:]
print(f"直近 {len(gaps)} 間隔: 中央値 {statistics.median(gaps):.1f} 時間 / 最大 {max(gaps):.1f} 時間")
idle = (now - rel[-1][1]).total_seconds() / 3600
print(f"最新 {rel[-1][0]} から {idle:.1f} 時間経過")
if __name__ == "__main__":
main()動かして気づいた落とし穴が二つありました
0 本の週が、黙って消えます
最初に書いた版では、Counter に入っているキーを並べて末尾 6 週を出していました。Claude Code では毎週公開があるので問題なく見えたのですが、試しに lodash を指定したところ、2019 年や 2020 年の週が「直近」として並んでしまいました。0 本の週は Counter にキーそのものが無く、並べた時点で消えているのです。
そこで、今日から 1 週間ずつ遡って週番号を作り、per_week.get(week, 0) で引く形に書き直しました。書き直した版で lodash を動かすと、直近 6 週がすべて 0 本と出て、最後の公開(4.18.1)から約 5,000 時間が経っていることも一緒に読み取れます。
火曜の昼は、今週がまだ 1 本に見えます
もう一つは数字の読み方です。W44 が 1 本と出ているのは、公開が減ったからではありません。週の前半に実行したため、まだ始まって一日ほどだからです。最新の公開は 10 月 26 日の 19 時台(UTC)で、実行時点で 7.3 時間前でした。
週の本数を比べるときは、完結した週(W39〜W43)だけを並べ、実行した週は別に扱うことにしました。この線引きを入れてから、「今週は少ない」と早合点しなくなりました。
次の一歩
まず、cadence.py を保存して、引数なしで一度だけ動かしてみてください。出てきた中央値が、ご自身の「新版は毎日出ている」という感覚と合うかどうかを確かめるだけで、更新を追う頻度の目安が定まります。
私自身は、個人開発で触れている道具の更新を「新版が出た直後」に当てるか「数日置く」かを決めるとき、感覚ではなくこの中央値を基準にしようと考えております。数えてみて初めて、置く日数の根拠が持てるのだと思います。