ClaudeMods
☰
JA
● 0 人がオンライン ・閲覧 0 回
スポンサー作品を投稿
公式サンプル · 投稿者 anthropics

telemetry

プラグイン分析:$.telemetry の2つのイベントを hook し、プラグインがイベントを記録したり機能の使用を first-party 行として印付けしたりして、セッション独自の資格情報でバッチ送信できるようにします。

翻訳済み

この mod について

telemetry

プラグインとして提供されるプラグイン分析です。telemetry.log と telemetry.mark の hook が2つのイベントの動作を担い、engine.create のステップから渡される名詞の上に構築されます。その上のゲートは Claude Code に組み込まれたプラグインだけに対応します。ユーザーがインストールしたプラグインや管理者が列挙したプラグインからの呼び出しは理由付きで拒否されます(ホストはすべての呼び出しに、それを発生させたプラグインと next.origin を刻み、ゲートはその層を読み取ります)。独自の $.telemetry を持たないエンジンでは同じステップが名詞を追加するため、そこでも呼び出しが存在します。エントリは to で送信先を示します。デフォルトの anthropic はこの mod の送信先で、collector はオペレーターが設定した telemetry collector です。collector はそのまま下層へ渡され、to が行の一部になることはありません。 $.telemetry.log({ event, props }) は1つのイベントを1つの first-party 行 tengu_plugin_<event> としてキューに入れます。$.telemetry.mark({ feature, kind, reason?, props? }) は CLI 自身の機能イベントと同じように、機能の1回の使用を tengu_feature_<kind> として印付けし、feature_name とその mark のプロパティを横に置きます。どちらも行がキューに入ると完了します。行はバッチで送信されます。最初の行をキューに入れて数秒後、セッション自身の資格情報を使ってイベントログの取り込み先へ1回 POST します(各バッチで $.session.authorize() を解決)。100件待つと直ちに送信し、セッション終了時にも送信します。取り込み先がサーバーエラー、タイムアウト、レート制限でバッチを拒否した場合は、もう1度試します。first-party 資格情報のないセッション、または取り込み先がなお拒否するバッチは破棄され、各結果は debug log に1行で記録されます。

各行には CLI 自身の行が持つ情報が含まれ、セッションごとに1度 $ を通じて集められます。イベント ID、インストールのデバイス ID、CLI のグローバル設定にあるサインイン済みアカウントの ID、セッション ID、モデル、クライアント種別、エントリポイント、対話性、そして env ブロック(1回の uname probe から得たプラットフォームとアーキテクチャ、ターミナル、shell、パッケージマネージャーとランタイム、CI と GitHub Actions、リモートコンテナ、デプロイ、Linux ディストリビューションとカーネル、WSL、作業ディレクトリのバージョン管理、$.session.version() から得たエンジンのバージョン、ベースバージョン、ビルド時刻。エンジンが答えない場合は空)が入り、行のプロパティの横にはリポジトリのリモート hash が置かれます。エンジンだけが知る情報(ランタイムのバージョン、プロセスのメモリ、リクエストの betas、サブスクリプション層、呼び出し元の agent)は $ にはないため、その列は空のままです。

CLI 自身の分析が無効になっている場所では何も送信しません。DISABLE_TELEMETRY、CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC、DO_NOT_TRACK の下、テスト実行中、ホストが管理しない第三者プロバイダー(Bedrock、Vertex、Foundry など)、クラウド gateway(環境のスイッチまたは管理ポリシーのログイン pins)、独自の OAuth URL を持つデプロイでは送信しません。各バッチの前に $.env と $.settings から毎回読み取るため、セッションがその後第三者プロバイダーや gateway に移った場合もこれ以上送信しません。スイッチを読めない場合も送信しません。USER_TYPE がそう示す場合、行の user_type は ant、そうでなければ external です。

自由形式の値が行に入ることはありません。イベント名とすべてのプロパティキーは snake_case token です。値は有限の数値、boolean、または Choice(選択肢リストとともに名前を付けた文字列)のいずれかで、log と mark の両方に適用されます。mark は ok、sad、bad を受け付け、後者2つには reason が必要で、最初のものでは拒否されます。ルールに違反するエントリはキューに入れる前に拒否されます。環境では、値が秘密である変数や人、ホストを名指しする変数について、設定されているかどうかだけを読み、それ以上は読みません。shell は閉じたリストから選んだ basename です。

hooks/register.ts がモジュールです。types/index.d.ts が名詞の契約であり、この mod の hook、名詞を呼び出す mod、応答するテストが読む $.telemetry の唯一の宣言です。

hook するもの

telemetry.* はゲートです。組み込み層(またはエンジン)の呼び出しは通り、それ以外は拒否され、ゲートが throw しても拒否されます。 telemetry.log と telemetry.mark はゲートの下にあり、エントリを検査して行をキューに入れます。hook は { value } を返し、ルール違反のエントリには理由付きの { deny } を返すため、呼び出し元の promise はその名前を示して reject します。engine.create では sender が await next(e) の上に構築され、ステップは { ...{ telemetry }, ...beneath } を上へ渡します。beneath が最後に展開されるため、下層に独自の telemetry があればそれが残り、なければこの mod のものが追加されます。下層のものは置き換えません。 session.start はプロンプトに人がいるかを知るため、session.end は残っているものを送るために使います。

$ で呼び出すもの

session.authorize、session.id、session.model、session.surfaces、session.cwd、session.repo、settings.read、env.get(スイッチと説明用の変数をリテラル名で取得)、fs.read、fs.list、fs.exists、process.run(uname と command -v を1回の sh -c で実行)、clock.after、clock.sleep、http.fetch、ui.log(debug log へ)を、fold から渡されたインターフェースでそれぞれ呼び出します。

動く場所と対象

このプラグインは CLI 自身が読み込み、自身の分析が有効なすべてのビルドに配置され、それ以外には存在しません。CLI に組み込まれたプラグインにサービスを提供し、他の呼び出し元はすべて拒否します。--plugin-dir でインストールしたり読み込んだりするためのものではありません。フォルダーにマニフェストがあるのはほかのプラグインと同じように読めるようにするためで、単独で動かすためではありません。このプラグインがない場所で組み込みプラグインが $.telemetry を呼ぶと、その名詞が見つからないか、独自の名詞を持つエンジンでは何もキューに入れない名詞が見つかります。どちらの場合も "no analytics here" です。

インストール

まず作者の README で marketplace とプラグイン名を確認してください。コマンドはリポジトリの構成によって変わる場合があります。

claude plugin marketplace add anthropics/claude-code
claude plugin install telemetry
原文 / README

telemetry

Plugin analytics as a plugin: its hooks on telemetry.log and telemetry.mark are what those two events do, built over the nouns its engine.create step is handed, and a gate above them serves the plugins built into Claude Code alone: a call from a plugin a person installed or an administrator listed is refused with a reason (the host stamps every call with the plugin that raised it, next.origin, and the gate reads its tier). On an engine that has no $.telemetry of its own the same step adds the noun, so the calls exist there too. An entry names where it goes with to: anthropic, the default, is this mod's; one for collector, the telemetry collector an operator configured, is passed on beneath untouched, and to is never part of a row. $.telemetry.log({ event, props }) queues one event as one first-party row, tengu_plugin_<event>; $.telemetry.mark({ feature, kind, reason?, props? }) marks one use of a feature as the CLI's own feature events do, tengu_feature_<kind> with a feature_name and the mark's properties beside it. Both resolve once the row is queued. Rows go out in batches: one POST to the event-logging ingest with the session's own credential ($.session.authorize(), resolved for each batch) a few seconds after the first row was queued, at once when a hundred wait, and when the session ends; a batch the ingest refuses with a server error, a timeout or a rate limit is tried once more. A session with no first-party credential, or an ingest that still refuses, drops the batch; each outcome is one line in the debug log.

Each row carries what the CLI's own rows carry, gathered through $ once a session: an event id, the install's device id and the signed-in account's ids from the CLI's global config, the session's id, model, client type, entrypoint and interactivity, and an env block (platform and architecture from one uname probe, terminal, shell, package managers and runtimes, CI and GitHub Actions, the remote container, the deployment, the Linux distribution and kernel, WSL, the working directory's version control, and the engine's version, base version and build time from $.session.version(), left empty on an engine that does not answer it), with the repository's remote hash beside the row's properties. What the engine alone knows (its runtime's version, the process's memory, the request's betas, the subscription tier, the calling agent) is not on $, and those columns stay empty.

It sends nothing wherever the CLI's own analytics are off: under DISABLE_TELEMETRY, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC or DO_NOT_TRACK, in a test run, on any third-party provider (Bedrock, Vertex, Foundry and kin) the host does not manage, on a cloud gateway (the environment's switch or the managed policy's login pins), and on a deployment with its own OAuth URL. Each is read through $.env and $.settings before every batch, so a session that has since moved to a third-party provider or a gateway sends nothing more; when the switches cannot be read, nothing is sent either. The row's user_type is ant when USER_TYPE says so, else external.

Nothing free-form reaches a row. An event name and every property key is a snake_case token; a value is a finite number, a boolean, or a Choice (a string named together with the list it is chosen from), under log and mark alike; mark takes ok, sad or bad, with a reason required on the last two and refused on the first. An entry that breaks a rule is refused before anything is queued. Of the environment, a variable whose value is a secret, or names a person or a host, is read for whether it is set and nothing more; a shell is its basename from a closed list.

hooks/register.ts is the module; types/index.d.ts is the noun's contract, the one declaration of $.telemetry that this mod's hooks, a mod calling the noun and a test answering it all read.

What it hooks

telemetry.*, the gate: a caller in the built-in tier (or the engine) goes on, any other is refused, and a gate that throws refuses too. telemetry.log and telemetry.mark, beneath the gate: the entry is checked and its row queued, the hook answering { value }, or { deny } with the reason for an entry that breaks a rule, so the caller's promise rejects naming it. engine.create: the sender is built over await next(e), and the step hands up { ...{ telemetry }, ...beneath }: what is beneath is spread last, so its own telemetry stands where it has one and this mod's is added where it has none; nothing beneath is replaced. session.start, to learn whether a person is at the prompt; session.end, to send what still waits.

What it calls on $

session.authorize, session.id, session.model, session.surfaces, session.cwd, session.repo, settings.read, env.get (the switches and the describing variables, by literal name), fs.read, fs.list, fs.exists, process.run (one sh -c of uname and command -v), clock.after, clock.sleep, http.fetch and ui.log (to the debug log), each on the interface the fold handed it.

Where it runs, whom it serves

This plugin is seated by the CLI itself, on every build whose own analytics are on, and nowhere else; it serves the plugins bundled with the CLI and refuses every other caller. It is not meant to be installed or loaded with --plugin-dir; the folder has a manifest so it reads like every other plugin, not so it can stand alone. A built-in that calls $.telemetry where this one is absent finds no such noun, or, on an engine with the noun of its own, one whose calls queue nothing; either way that is "no analytics here".

関連作品