Skip to content
Claude Code Mods

Mod

telemetry

Source verified. Source URL responded on 2026-09-21. Not a security review.Built in
  • Observability
License
© Anthropic PBC. All rights reserved. Use is subject to Anthropic's Commercial Terms of Service.

Adds $.telemetry (log, mark) in the engine.create fold so built-in plugins can record first-party analytics rows, sent in batches; refuses installed plugins.

Notice

Early access. Hooks modules load only where function hooks are enabled, and the API these mods are written against may change between releases without notice. They are not listed in the repository's marketplace; the copies that matter are the ones already in your Claude Code.

On this page

What it does

telemetry is plugin analytics as a plugin. One engine.create step adds $.telemetry to the engine interface that every plugin above it is handed, built over the nouns beneath. A hook on the plugin's own two events 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.

$.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), with the repository's remote hash beside the row's properties. What the engine alone knows (its version and build time, its runtime's version, the process's memory, the request's betas, the subscription tier, the calling agent) is not on $, so 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, and a shell is its basename from a closed list.

How it works

The module is hooks/register.ts, and 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.

engine.create: returns { ...await next(e), telemetry }, so the noun is added and nothing beneath is replaced.

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.

session.start: to learn whether a person is at the prompt.

session.end: to send what still waits.

On $ it calls 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.

Other mods call the noun. The diff and agents-md mods call $.telemetry, and where this plugin is absent they drop their rows and nothing else changes.

Set up

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.

The README says plainly that 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. For that reason this listing gives no run-from-source command.

It has no configuration options: its plugin.json declares no userConfig. The README documents no switch for this plugin itself. It sends nothing wherever the CLI's own analytics are off, under DISABLE_TELEMETRY, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC or DO_NOT_TRACK, and the overview lists the other cases.

A built-in that calls $.telemetry where this plugin is absent finds no such noun and should treat that as no analytics here.

The source does not document how to enable function hooks. The author of the announcement issue (anthropics/claude-code #91870) wrote in its Sep 9, 2026 update that anyone who wants to test can start Claude Code with CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1. That is a note in an issue, not documentation, and it may change without notice.

Download the source

The source lives in the mods/telemetry folder of the anthropics/claude-code repository. To fetch only that folder and the mods/types declarations it is typed against, clone the repository sparsely, enter it, and check out those two folders. The clone also brings the files at the top level of the repository.

The repository's LICENSE.md reads: "© Anthropic PBC. All rights reserved. Use is subject to Anthropic's Commercial Terms of Service." The mods README says this folder is the source of the mods, published as it is built into the binary, so that it can be read. This listing does not call it open source.

git clone --depth 1 --filter=blob:none --sparse https://github.com/anthropics/claude-code.git

cd claude-code

git sparse-checkout set mods/telemetry mods/types

Test it

Run the command below from the root of a clone of the repository. Tests live in the mod's tests/ folder, which holds 2 test files (tests/gate.test.ts and tests/register.test.ts) and a fixtures folder as of the source read for this listing. The README describes no per-test coverage beyond that.

Per the mods README, a test gets the engine's own $ and a plugin's on. Each call on $ is one the engine makes, through every hook of the mod loaded as it ships. The hooks a test registers with on sit beneath the mod, where the rest of the world would be, and a call they leave unanswered throws, naming its event. A test file is named for what it covers under hooks/, and the kit's mock answers the world beneath the mod from memory (mock.env, mock.store, mock.clock).

The mods README also says that tsc -p mods/tsconfig.json typechecks every mod's hooks and tests against types/ and each mod's own types contract.

claude plugin test mods/telemetry

Hooks it registers

What the badge means

Source verified means the source URL for this entry responded with HTTP 200 on . That is the whole claim. Nobody has read, scanned or run this code on your behalf, and the badge does not mean Anthropic or anyone else endorses it.

Sources change after the check date. Read the code and the publisher page before you install. How to check an extension

  • Plugin

    Source verified. Source URL responded on 2026-09-20. Not a security review.

    session-report

    Generates an explorable HTML report of Claude Code usage from local session transcripts: tokens, cache, subagents, skills, costly prompts.

    • Observability
    • Optimization